From 74fb6455893a02403236d4fc22e15d491b81261c Mon Sep 17 00:00:00 2001 From: Deyan Gigov Date: Fri, 13 Feb 2026 10:08:21 +0200 Subject: [PATCH 1/8] feat: add auto theme functionality to OverType editor - Implemented auto theme switching based on system color scheme preference. - Added `auto` theme to themes registry, defaulting to solar colors. - Enhanced `setTheme` method to handle auto theme and resolved theme application. - Introduced media query listeners for real-time theme updates. - Updated example pages to demonstrate auto theme functionality. - Created tests for auto theme behavior at both instance and global levels. --- CHANGELOG.md | 11 ++ README.md | 30 +++- dist/overtype-webcomponent.esm.js | 192 ++++++++++++++++++++--- dist/overtype-webcomponent.js | 192 ++++++++++++++++++++--- dist/overtype-webcomponent.min.js | 78 +++++----- dist/overtype.cjs | 192 ++++++++++++++++++++--- dist/overtype.esm.js | 192 ++++++++++++++++++++--- dist/overtype.esm.js.map | 4 +- dist/overtype.js | 192 ++++++++++++++++++++--- dist/overtype.js.map | 4 +- dist/overtype.min.js | 66 ++++---- package-lock.json | 2 + src/overtype.js | 242 +++++++++++++++++++++++++---- src/themes.js | 35 +++++ test/auto-theme.test.js | 156 +++++++++++++++++++ website/examples/auto-theme.html | 243 ++++++++++++++++++++++++++++++ website/examples/index.html | 10 ++ website/index.html | 4 +- 18 files changed, 1645 insertions(+), 200 deletions(-) create mode 100644 test/auto-theme.test.js create mode 100644 website/examples/auto-theme.html diff --git a/CHANGELOG.md b/CHANGELOG.md index f718845..83df48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- Auto theme that automatically switches between solar and cave based on system color scheme preference +- Real-time theme updates when system color scheme changes +- `resolveAutoTheme()` and `getSystemColorScheme()` helper functions in themes.js +- Auto theme example page demonstrating system theme detection + +### Changed +- Updated TypeScript definitions to include auto theme +- Enhanced theme switching to support media query listeners +- Improved theme cleanup in destroy method + ## [2.0.6] - 2025-11-19 ### 🐛 Bug Fixes diff --git a/README.md b/README.md index 7a9aaed..fee989a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OverType -A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay technique. Includes optional toolbar. ~95KB minified with all features. +A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay technique. Includes optional toolbar. ~98KB minified with all features. ## Live Examples @@ -15,11 +15,12 @@ A lightweight markdown editor library with perfect WYSIWYG alignment using an in ## Features - 👻 **Invisible textarea overlay** - Transparent input layer overlaid on styled preview for seamless editing -- 🎨 **Global theming** - Solar (light) and Cave (dark) themes that apply to all instances +- 🎨 **Global theming** - Solar (light), Cave (dark), and Auto themes that apply to all instances +- 🌓 **System theme detection** - Auto theme adapts to system color scheme preference - ⌨️ **Keyboard shortcuts** - Common markdown shortcuts (Cmd/Ctrl+B for bold, etc.) - 📱 **Mobile optimized** - Responsive design with mobile-specific styles - 🔄 **DOM persistence aware** - Recovers from existing DOM (perfect for HyperClay and similar platforms) -- 🚀 **Lightweight** - ~95KB minified +- 🚀 **Lightweight** - ~98KB minified - 🎯 **Optional toolbar** - Clean, minimal toolbar with all essential formatting - ✨ **Smart shortcuts** - Keyboard shortcuts with selection preservation - 📝 **Smart list continuation** - GitHub-style automatic list continuation on Enter @@ -35,7 +36,7 @@ We overlap an invisible textarea on top of styled output, giving the illusion of | Feature | OverType | HyperMD | Milkdown | TUI Editor | EasyMDE | |---------|----------|---------|----------|------------|---------| -| **Size** | ~95KB | 364.02 KB | 344.51 KB | 560.99 KB | 323.69 KB | +| **Size** | ~98KB | 364.02 KB | 344.51 KB | 560.99 KB | 323.69 KB | | **Dependencies** | Bundled | CodeMirror | ProseMirror + plugins | Multiple libs | CodeMirror | | **Setup** | Single file | Complex config | Build step required | Complex config | Moderate | | **Approach** | Invisible textarea | ContentEditable | ContentEditable | ContentEditable | CodeMirror | @@ -264,6 +265,25 @@ const [editor] = new OverType('#editor', { }); ``` +### Auto Theme + +Automatically switch between light and dark themes based on the system's color scheme preference: + +```javascript +const [editor] = new OverType('#editor', { + theme: 'auto' // Automatically uses 'solar' or 'cave' based on system preference +}); + +// Set auto theme globally +OverType.setTheme('auto'); +``` + +The `auto` theme: +- Automatically switches between `solar` (light) and `cave` (dark) themes +- Responds to system theme changes in real-time +- Works at both instance and global levels +- Ideal for apps that respect user system preferences + ### Preview & HTML Export Generate HTML previews or export the rendered content: @@ -418,7 +438,7 @@ new OverType(target, options) fontFamily: 'monospace', padding: '16px', - // Theme - 'solar', 'cave', or custom theme object + // Theme - 'solar' (light), 'cave' (dark), 'auto' (system), or custom theme object theme: 'solar', // Custom colors (override theme colors) diff --git a/dist/overtype-webcomponent.esm.js b/dist/overtype-webcomponent.esm.js index 9a3574e..82e60e8 100644 --- a/dist/overtype-webcomponent.esm.js +++ b/dist/overtype-webcomponent.esm.js @@ -1,5 +1,5 @@ /** - * OverType v2.1.0 + * OverType v2.1.1 * A lightweight markdown editor library with perfect WYSIWYG alignment * @license MIT * @author David Miranda @@ -914,9 +914,16 @@ var cave = { // Even lighter - active button background } }; +var auto = { + name: "auto", + // The auto theme doesn't have its own colors; it uses solar or cave dynamically + colors: solar.colors + // Default to solar colors for initial render +}; var themes = { solar, cave, + auto, // Aliases for backward compatibility light: solar, dark: cave @@ -928,6 +935,13 @@ function getTheme(theme) { } return theme; } +function resolveAutoTheme(themeName) { + if (themeName !== "auto") { + return themeName; + } + const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; + return isDarkMode ? "cave" : "solar"; +} function themeToCSSVars(colors) { const vars = []; for (const [key, value] of Object.entries(colors)) { @@ -3359,6 +3373,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { + // Listener function for auto theme changes /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -3402,6 +3417,8 @@ var _OverType = class _OverType { _init(element, options = {}) { this.element = element; this.instanceTheme = options.theme || null; + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; this.options = this._mergeOptions(options); this.instanceId = ++_OverType.instanceCount; this.initialized = false; @@ -3414,6 +3431,9 @@ var _OverType = class _OverType { } else { this._buildFromScratch(); } + if (this.instanceTheme) { + this.setTheme(this.instanceTheme); + } this.shortcuts = new ShortcutsManager(this); this._rebuildActionsMap(); this.linkTooltip = new LinkTooltip(this); @@ -4053,18 +4073,73 @@ var _OverType = class _OverType { * @returns {this} Returns this for chaining */ setTheme(theme) { + this._cleanupAutoThemeListener(); this.instanceTheme = theme; - const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName) { - this.container.setAttribute("data-theme", themeName); + if (theme === "auto") { + this._setupAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + this._applyResolvedTheme(resolvedTheme); + } else { + const themeObj = typeof theme === "string" ? getTheme(theme) : theme; + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName) { + this.container.setAttribute("data-theme", themeName); + } + if (themeObj && themeObj.colors) { + const cssVars = themeToCSSVars(themeObj.colors); + this.container.style.cssText += cssVars; + } + this.updatePreview(); } + return this; + } + /** + * Apply a resolved theme name (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + */ + _applyResolvedTheme(themeName) { + const themeObj = getTheme(themeName); + this.container.setAttribute("data-theme", "auto"); + this.container.setAttribute("data-resolved-theme", themeName); if (themeObj && themeObj.colors) { const cssVars = themeToCSSVars(themeObj.colors); this.container.style.cssText += cssVars; } this.updatePreview(); - return this; + } + /** + * Setup auto theme listener for instance + * @private + */ + _setupAutoThemeListener() { + if (!window.matchMedia) + return; + this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + this.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + this._applyResolvedTheme(resolvedTheme); + }; + if (this.autoThemeMediaQuery.addEventListener) { + this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.addListener) { + this.autoThemeMediaQuery.addListener(this.autoThemeListener); + } + } + /** + * Clean up auto theme listener for instance + * @private + */ + _cleanupAutoThemeListener() { + if (this.autoThemeMediaQuery && this.autoThemeListener) { + if (this.autoThemeMediaQuery.removeEventListener) { + this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.removeListener) { + this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + } + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; + } } /** * Set instance-specific code highlighter @@ -4218,6 +4293,7 @@ var _OverType = class _OverType { * Destroy the editor instance */ destroy() { + this._cleanupAutoThemeListener(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4323,40 +4399,117 @@ var _OverType = class _OverType { * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + _OverType._cleanupGlobalAutoThemeListener(); + if (theme === "auto") { + _OverType._setupGlobalAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + } else { + let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + if (customColors) { + themeObj = mergeTheme(themeObj, customColors); + } + _OverType.currentTheme = themeObj; + _OverType.injectStyles(true); + document.querySelectorAll(".overtype-container").forEach((container) => { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + container.setAttribute("data-theme", themeName2); + } + }); + document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { + if (!wrapper.closest(".overtype-container")) { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + wrapper.setAttribute("data-theme", themeName2); + } + } + const instance = wrapper._instance; + if (instance) { + instance.updatePreview(); + } + }); + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + document.querySelectorAll("overtype-editor").forEach((webComponent) => { + if (themeName && typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", themeName); + } + if (typeof webComponent.refreshTheme === "function") { + webComponent.refreshTheme(); + } + }); + } + } + /** + * Apply a resolved theme globally (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + * @param {Object} customColors - Optional color overrides + */ + static _applyGlobalResolvedTheme(themeName, customColors = null) { + let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } + container.setAttribute("data-theme", "auto"); + container.setAttribute("data-resolved-theme", themeName); }); document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); } const instance = wrapper._instance; if (instance) { instance.updatePreview(); } }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); + if (typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", "auto"); + webComponent.setAttribute("data-resolved-theme", themeName); } if (typeof webComponent.refreshTheme === "function") { webComponent.refreshTheme(); } }); } + /** + * Setup global auto theme listener + * @private + */ + static _setupGlobalAutoThemeListener() { + if (!window.matchMedia) + return; + _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + _OverType._applyGlobalResolvedTheme(resolvedTheme); + }; + if (_OverType.autoThemeMediaQuery.addEventListener) { + _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.addListener) { + _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + } + } + /** + * Clean up global auto theme listener + * @private + */ + static _cleanupGlobalAutoThemeListener() { + if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { + if (_OverType.autoThemeMediaQuery.removeEventListener) { + _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.removeListener) { + _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + } + _OverType.autoThemeMediaQuery = null; + _OverType.autoThemeListener = null; + } + } /** * Set global code highlighter for all OverType instances * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML @@ -4458,6 +4611,9 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); +__publicField(_OverType, "autoThemeMediaQuery", null); +// Media query for auto theme switching +__publicField(_OverType, "autoThemeListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype-webcomponent.js b/dist/overtype-webcomponent.js index a1e631b..9d01e26 100644 --- a/dist/overtype-webcomponent.js +++ b/dist/overtype-webcomponent.js @@ -1,5 +1,5 @@ /** - * OverType v2.1.0 + * OverType v2.1.1 * A lightweight markdown editor library with perfect WYSIWYG alignment * @license MIT * @author David Miranda @@ -937,9 +937,16 @@ var OverTypeEditor = (() => { // Even lighter - active button background } }; + var auto = { + name: "auto", + // The auto theme doesn't have its own colors; it uses solar or cave dynamically + colors: solar.colors + // Default to solar colors for initial render + }; var themes = { solar, cave, + auto, // Aliases for backward compatibility light: solar, dark: cave @@ -951,6 +958,13 @@ var OverTypeEditor = (() => { } return theme; } + function resolveAutoTheme(themeName) { + if (themeName !== "auto") { + return themeName; + } + const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; + return isDarkMode ? "cave" : "solar"; + } function themeToCSSVars(colors) { const vars = []; for (const [key, value] of Object.entries(colors)) { @@ -3382,6 +3396,7 @@ ${blockSuffix}` : suffix; return false; } var _OverType = class _OverType { + // Listener function for auto theme changes /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -3425,6 +3440,8 @@ ${blockSuffix}` : suffix; _init(element, options = {}) { this.element = element; this.instanceTheme = options.theme || null; + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; this.options = this._mergeOptions(options); this.instanceId = ++_OverType.instanceCount; this.initialized = false; @@ -3437,6 +3454,9 @@ ${blockSuffix}` : suffix; } else { this._buildFromScratch(); } + if (this.instanceTheme) { + this.setTheme(this.instanceTheme); + } this.shortcuts = new ShortcutsManager(this); this._rebuildActionsMap(); this.linkTooltip = new LinkTooltip(this); @@ -4076,18 +4096,73 @@ ${blockSuffix}` : suffix; * @returns {this} Returns this for chaining */ setTheme(theme) { + this._cleanupAutoThemeListener(); this.instanceTheme = theme; - const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName) { - this.container.setAttribute("data-theme", themeName); + if (theme === "auto") { + this._setupAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + this._applyResolvedTheme(resolvedTheme); + } else { + const themeObj = typeof theme === "string" ? getTheme(theme) : theme; + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName) { + this.container.setAttribute("data-theme", themeName); + } + if (themeObj && themeObj.colors) { + const cssVars = themeToCSSVars(themeObj.colors); + this.container.style.cssText += cssVars; + } + this.updatePreview(); } + return this; + } + /** + * Apply a resolved theme name (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + */ + _applyResolvedTheme(themeName) { + const themeObj = getTheme(themeName); + this.container.setAttribute("data-theme", "auto"); + this.container.setAttribute("data-resolved-theme", themeName); if (themeObj && themeObj.colors) { const cssVars = themeToCSSVars(themeObj.colors); this.container.style.cssText += cssVars; } this.updatePreview(); - return this; + } + /** + * Setup auto theme listener for instance + * @private + */ + _setupAutoThemeListener() { + if (!window.matchMedia) + return; + this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + this.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + this._applyResolvedTheme(resolvedTheme); + }; + if (this.autoThemeMediaQuery.addEventListener) { + this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.addListener) { + this.autoThemeMediaQuery.addListener(this.autoThemeListener); + } + } + /** + * Clean up auto theme listener for instance + * @private + */ + _cleanupAutoThemeListener() { + if (this.autoThemeMediaQuery && this.autoThemeListener) { + if (this.autoThemeMediaQuery.removeEventListener) { + this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.removeListener) { + this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + } + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; + } } /** * Set instance-specific code highlighter @@ -4241,6 +4316,7 @@ ${blockSuffix}` : suffix; * Destroy the editor instance */ destroy() { + this._cleanupAutoThemeListener(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4346,40 +4422,117 @@ ${blockSuffix}` : suffix; * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + _OverType._cleanupGlobalAutoThemeListener(); + if (theme === "auto") { + _OverType._setupGlobalAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + } else { + let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + if (customColors) { + themeObj = mergeTheme(themeObj, customColors); + } + _OverType.currentTheme = themeObj; + _OverType.injectStyles(true); + document.querySelectorAll(".overtype-container").forEach((container) => { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + container.setAttribute("data-theme", themeName2); + } + }); + document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { + if (!wrapper.closest(".overtype-container")) { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + wrapper.setAttribute("data-theme", themeName2); + } + } + const instance = wrapper._instance; + if (instance) { + instance.updatePreview(); + } + }); + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + document.querySelectorAll("overtype-editor").forEach((webComponent) => { + if (themeName && typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", themeName); + } + if (typeof webComponent.refreshTheme === "function") { + webComponent.refreshTheme(); + } + }); + } + } + /** + * Apply a resolved theme globally (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + * @param {Object} customColors - Optional color overrides + */ + static _applyGlobalResolvedTheme(themeName, customColors = null) { + let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } + container.setAttribute("data-theme", "auto"); + container.setAttribute("data-resolved-theme", themeName); }); document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); } const instance = wrapper._instance; if (instance) { instance.updatePreview(); } }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); + if (typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", "auto"); + webComponent.setAttribute("data-resolved-theme", themeName); } if (typeof webComponent.refreshTheme === "function") { webComponent.refreshTheme(); } }); } + /** + * Setup global auto theme listener + * @private + */ + static _setupGlobalAutoThemeListener() { + if (!window.matchMedia) + return; + _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + _OverType._applyGlobalResolvedTheme(resolvedTheme); + }; + if (_OverType.autoThemeMediaQuery.addEventListener) { + _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.addListener) { + _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + } + } + /** + * Clean up global auto theme listener + * @private + */ + static _cleanupGlobalAutoThemeListener() { + if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { + if (_OverType.autoThemeMediaQuery.removeEventListener) { + _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.removeListener) { + _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + } + _OverType.autoThemeMediaQuery = null; + _OverType.autoThemeListener = null; + } + } /** * Set global code highlighter for all OverType instances * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML @@ -4481,6 +4634,9 @@ ${blockSuffix}` : suffix; __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); + __publicField(_OverType, "autoThemeMediaQuery", null); + // Media query for auto theme switching + __publicField(_OverType, "autoThemeListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype-webcomponent.min.js b/dist/overtype-webcomponent.min.js index f7b24ef..60bfe6b 100644 --- a/dist/overtype-webcomponent.min.js +++ b/dist/overtype-webcomponent.min.js @@ -1,19 +1,19 @@ /** - * OverType v2.1.0 + * OverType v2.1.1 * A lightweight markdown editor library with perfect WYSIWYG alignment * @license MIT * @author David Miranda * https://github.com/panphora/overtype */ -var OverTypeEditor=(()=>{var j=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var Re=Object.getOwnPropertyNames;var Ve=Object.prototype.hasOwnProperty;var Ue=(n,e,t)=>e in n?j(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var De=(n,e)=>{for(var t in e)j(n,t,{get:e[t],enumerable:!0})},qe=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Re(e))!Ve.call(n,o)&&o!==t&&j(n,o,{get:()=>e[o],enumerable:!(i=Fe(e,o))||i.enumerable});return n};var We=n=>qe(j({},"__esModule",{value:!0}),n);var E=(n,e,t)=>(Ue(n,typeof e!="symbol"?e+"":e,t),t);var ct={};De(ct,{default:()=>lt});var L=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,i=>t[i])}static preserveIndentation(e,t){let o=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,o)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,i,o)=>{let r=i.length;return`${i} ${o}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
${e}
`:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,i)=>`> ${i}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,i,o,r)=>`${i}
  • ${o} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(i,o,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${o}
  • ${s}
  • `}else return`${o}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,i,o,r)=>`${i}
  • ${o} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),i=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>i.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,i,o)=>{let r=`--link-${this.linkIndex++}`;return`[${i}](${o})`})}static identifyAndProtectSanctuaries(e){let t=new Map,i=0,o=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,u=h+a[2].length;r.push({start:h,end:u})}let c=new RegExp("(?p>=f.start&&h<=f.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((p,h)=>h.index-p.index),l.forEach(p=>{let h=`\uE000${i++}\uE001`;t.set(h,{type:"code",original:p.match,openTicks:p.openTicks,content:p.content,closeTicks:p.closeTicks}),o=o.substring(0,p.index)+h+o.substring(p.index+p.match.length)}),o=o.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(p,h,u)=>{let f=`\uE000${i++}\uE001`;return t.set(f,{type:"link",original:p,linkText:h,url:u}),f}),{protectedText:o,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((o,r)=>{let s=e.indexOf(o),a=e.indexOf(r);return s-a}).forEach(o=>{let r=t.get(o),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,p)=>{if(a.includes(p)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(p,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let c=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(o,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:i}=this.identifyAndProtectSanctuaries(e),o=t;return o=this.parseStrikethrough(o),o=this.parseBold(o),o=this.parseItalic(o),o=this.restoreAndTransformSanctuaries(o,i),o}static parseLine(e,t=!1){let i=this.escapeHtml(e);i=this.preserveIndentation(i,e);let o=this.parseHorizontalRule(i);if(o)return o;let r=this.parseCodeBlock(i);return r||(i=this.parseHeader(i),i=this.parseBlockquote(i),i=this.parseTaskList(i,t),i=this.parseBulletList(i),i=this.parseNumberedList(i),i=this.parseInlineElements(i),i.trim()===""?"
     
    ":`
    ${i}
    `)}static parse(e,t=-1,i=!1,o,r=!1){this.resetLinkIndex();let s=e.split(` -`),a=!1,d=s.map((l,p)=>{if(i&&p===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let u=this.escapeHtml(l);return`
    ${this.preserveIndentation(u,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,o)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let i=document.createElement("div");i.innerHTML=e;let o=null,r=null,s=null,a=!1,c=Array.from(i.children);for(let d=0;d0&&(s._codeContent+=` -`);let f=l.textContent.replace(/\u00A0/g," ");s._codeContent+=f,u.textContent.length>0&&(u.textContent+=` -`),u.textContent+=f,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let u=h.classList.contains("bullet-list"),f=h.classList.contains("ordered-list");if(!u&&!f){o=null,r=null;continue}let m=u?"ul":"ol";(!o||r!==m)&&(o=document.createElement(m),i.insertBefore(o,l),r=m);let g=[];for(let v of l.childNodes)if(v.nodeType===3&&v.textContent.match(/^\u00A0+$/))g.push(v.cloneNode(!0));else if(v===h)break;g.forEach(v=>{h.insertBefore(v,h.firstChild)}),o.appendChild(h),l.remove()}else o=null,r=null}return i.innerHTML}static postProcessHTMLManual(e,t){let i=e;i=i.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    • /,`
    • ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),i=i.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    2. /,`
    3. ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let o=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return i=i.replace(o,(r,s,a,c)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(g=>g.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` -`),p=s.slice(3).trim(),h=p?` class="language-${p}"`:"",u=l,f=t||this.codeHighlighter;if(f)try{let g=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),v=f(g,p);v&&typeof v.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):v&&typeof v=="string"&&v.trim()&&(u=v)}catch(g){console.warn("Code highlighting failed:",g)}let m=`
    ${s}
    `;return m+=`
    ${u}
    `,m+=`
    ${c}
    `,m}),i}static getListContext(e,t){let i=e.split(` +var OverTypeEditor=(()=>{var j=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var Ve=Object.getOwnPropertyNames;var Ue=Object.prototype.hasOwnProperty;var De=(n,e,t)=>e in n?j(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var qe=(n,e)=>{for(var t in e)j(n,t,{get:e[t],enumerable:!0})},We=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Ve(e))!Ue.call(n,o)&&o!==t&&j(n,o,{get:()=>e[o],enumerable:!(i=Fe(e,o))||i.enumerable});return n};var Ke=n=>We(j({},"__esModule",{value:!0}),n);var T=(n,e,t)=>(De(n,typeof e!="symbol"?e+"":e,t),t);var dt={};qe(dt,{default:()=>pt});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,i=>t[i])}static preserveIndentation(e,t){let o=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,o)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,i,o)=>{let r=i.length;return`${i} ${o}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,i)=>`> ${i}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,i,o,r)=>`${i}
  • ${o} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(i,o,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${o}
  • ${s}
  • `}else return`${o}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,i,o,r)=>`${i}
  • ${o} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),i=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>i.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,i,o)=>{let r=`--link-${this.linkIndex++}`;return`[${i}](${o})`})}static identifyAndProtectSanctuaries(e){let t=new Map,i=0,o=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,u=h+a[2].length;r.push({start:h,end:u})}let c=new RegExp("(?p>=g.start&&h<=g.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((p,h)=>h.index-p.index),l.forEach(p=>{let h=`\uE000${i++}\uE001`;t.set(h,{type:"code",original:p.match,openTicks:p.openTicks,content:p.content,closeTicks:p.closeTicks}),o=o.substring(0,p.index)+h+o.substring(p.index+p.match.length)}),o=o.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(p,h,u)=>{let g=`\uE000${i++}\uE001`;return t.set(g,{type:"link",original:p,linkText:h,url:u}),g}),{protectedText:o,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((o,r)=>{let s=e.indexOf(o),a=e.indexOf(r);return s-a}).forEach(o=>{let r=t.get(o),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,p)=>{if(a.includes(p)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(p,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let c=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(o,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:i}=this.identifyAndProtectSanctuaries(e),o=t;return o=this.parseStrikethrough(o),o=this.parseBold(o),o=this.parseItalic(o),o=this.restoreAndTransformSanctuaries(o,i),o}static parseLine(e,t=!1){let i=this.escapeHtml(e);i=this.preserveIndentation(i,e);let o=this.parseHorizontalRule(i);if(o)return o;let r=this.parseCodeBlock(i);return r||(i=this.parseHeader(i),i=this.parseBlockquote(i),i=this.parseTaskList(i,t),i=this.parseBulletList(i),i=this.parseNumberedList(i),i=this.parseInlineElements(i),i.trim()===""?"
     
    ":`
    ${i}
    `)}static parse(e,t=-1,i=!1,o,r=!1){this.resetLinkIndex();let s=e.split(` +`),a=!1,d=s.map((l,p)=>{if(i&&p===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let u=this.escapeHtml(l);return`
    ${this.preserveIndentation(u,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,o)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let i=document.createElement("div");i.innerHTML=e;let o=null,r=null,s=null,a=!1,c=Array.from(i.children);for(let d=0;d0&&(s._codeContent+=` +`);let g=l.textContent.replace(/\u00A0/g," ");s._codeContent+=g,u.textContent.length>0&&(u.textContent+=` +`),u.textContent+=g,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let u=h.classList.contains("bullet-list"),g=h.classList.contains("ordered-list");if(!u&&!g){o=null,r=null;continue}let f=u?"ul":"ol";(!o||r!==f)&&(o=document.createElement(f),i.insertBefore(o,l),r=f);let v=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))v.push(y.cloneNode(!0));else if(y===h)break;v.forEach(y=>{h.insertBefore(y,h.firstChild)}),o.appendChild(h),l.remove()}else o=null,r=null}return i.innerHTML}static postProcessHTMLManual(e,t){let i=e;i=i.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    • /,`
    • ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),i=i.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    2. /,`
    3. ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let o=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return i=i.replace(o,(r,s,a,c)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(v=>v.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` +`),p=s.slice(3).trim(),h=p?` class="language-${p}"`:"",u=l,g=t||this.codeHighlighter;if(g)try{let v=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=g(v,p);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(u=y)}catch(v){console.warn("Code highlighting failed:",v)}let f=`
    ${s}
    `;return f+=`
    ${u}
    `,f+=`
    ${c}
    `,f}),i}static getListContext(e,t){let i=e.split(` `),o=0,r=0,s=0;for(let h=0;h=t){r=h,s=o;break}o+=u+1}let a=i[r],c=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:c,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:c,markerEndPos:s+l[1].length+l[2].length+1};let p=a.match(this.LIST_PATTERNS.numbered);return p?{inList:!0,listType:"numbered",indent:p[1],marker:parseInt(p[2]),content:p[3],lineStart:s,lineEnd:c,markerEndPos:s+p[1].length+p[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:c,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` `),i=new Map,o=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let c=a[1],d=c.length,l=a[3];o||i.clear();let p=(i.get(d)||0)+1;i.set(d,p);for(let[h]of i)h>d&&i.delete(h);return o=!0,`${c}${p}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(o=!1,i.clear()),s}).join(` -`)}};E(L,"linkIndex",0),E(L,"codeHighlighter",null),E(L,"customSyntax",null),E(L,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let o=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(o="toggleBold");break;case"i":e.shiftKey||(o="toggleItalic");break;case"k":e.shiftKey||(o="insertLink");break;case"7":e.shiftKey&&(o="toggleNumberedList");break;case"8":e.shiftKey&&(o="toggleBulletList");break}return o?(e.preventDefault(),this.editor.performAction(o,e),!0):!1}destroy(){}};var M={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},Y={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},ee={solar:M,cave:Y,light:M,dark:Y};function T(n){return typeof n=="string"?{...ee[n]||ee.solar,name:n}:n}function B(n){let e=[];for(let[t,i]of Object.entries(n)){let o=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${o}: ${i};`)}return e.join(` -`)}function te(n,e={}){return{...n,colors:{...n.colors,...e}}}function F(n={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:i='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:o="20px",theme:r=null,mobile:s={}}=n,a=Object.keys(s).length>0?` +`)}};T(S,"linkIndex",0),T(S,"codeHighlighter",null),T(S,"customSyntax",null),T(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let o=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(o="toggleBold");break;case"i":e.shiftKey||(o="toggleItalic");break;case"k":e.shiftKey||(o="insertLink");break;case"7":e.shiftKey&&(o="toggleNumberedList");break;case"8":e.shiftKey&&(o="toggleBulletList");break}return o?(e.preventDefault(),this.editor.performAction(o,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},te={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},Qe={name:"auto",colors:A.colors},ie={solar:A,cave:te,auto:Qe,light:A,dark:te};function E(n){return typeof n=="string"?{...ie[n]||ie.solar,name:n}:n}function Q(n){return n!=="auto"?n:window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"cave":"solar"}function B(n){let e=[];for(let[t,i]of Object.entries(n)){let o=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${o}: ${i};`)}return e.join(` +`)}function G(n,e={}){return{...n,colors:{...n.colors,...e}}}function R(n={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:i='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:o="20px",theme:r=null,mobile:s={}}=n,a=Object.keys(s).length>0?` @media (max-width: 640px) { .overtype-wrapper .overtype-input, .overtype-wrapper .overtype-preview { @@ -861,28 +861,28 @@ var OverTypeEditor=(()=>{var j=Object.defineProperty;var Fe=Object.getOwnPropert } ${a} - `}var Ke=Object.defineProperty,ie=Object.getOwnPropertySymbols,Ze=Object.prototype.hasOwnProperty,Je=Object.prototype.propertyIsEnumerable,ne=(n,e,t)=>e in n?Ke(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,oe=(n,e)=>{for(var t in e||(e={}))Ze.call(e,t)&&ne(n,t,e[t]);if(ie)for(var t of ie(e))Je.call(e,t)&&ne(n,t,e[t]);return n},_={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Ge(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function H(n){return oe(oe({},Ge()),n)}var V=!1;function Qe(){return V}function y(n,e,t){V&&(console.group(`\u{1F50D} ${n}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function R(n,e){if(!V)return;let t=n.value.slice(n.selectionStart,n.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let i=n.value.slice(Math.max(0,n.selectionStart-10),n.selectionStart),o=n.value.slice(n.selectionEnd,Math.min(n.value.length,n.selectionEnd+10));console.log("Context:",JSON.stringify(i)+"[SELECTION]"+JSON.stringify(o)),console.groupEnd()}function le(n){V&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(n.text)),console.log("New selection:",`${n.selectionStart}-${n.selectionEnd}`),console.groupEnd())}var A=null;function I(n,{text:e,selectionStart:t,selectionEnd:i}){let o=Qe();o&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",i)),n.focus();let r=n.selectionStart,s=n.selectionEnd,a=n.value.slice(0,r),c=n.value.slice(s);o&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(n.value.slice(r,s))));let d=n.value,l=r!==s;if(A===null||A===!0){n.contentEditable="true";try{A=document.execCommand("insertText",!1,e),o&&console.log("execCommand returned:",A,"for text with",e.split(` -`).length,"lines")}catch(p){A=!1,o&&console.log("execCommand threw error:",p)}n.contentEditable="false"}if(o&&(console.log("canInsertText before:",A),console.log("execCommand result:",A)),A){let p=a+e+c,h=n.value;o&&(console.log("Expected length:",p.length),console.log("Actual length:",h.length)),h!==p&&o&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(p.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!A)if(o&&console.log("Using manual insertion"),n.value===d){o&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(p){}n.value=a+e+c;try{document.execCommand("ms-endUndoUnit")}catch(p){}n.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else o&&console.log("Value was changed by execCommand, skipping manual insertion");o&&console.log("Setting selection range:",t,i),t!=null&&i!=null?n.setSelectionRange(t,i):n.setSelectionRange(r,n.selectionEnd),o&&(console.log("Final value length:",n.value.length),console.groupEnd())}function re(n){return n.trim().split(` -`).length>1}function Xe(n,e){let t=e;for(;n[t]&&n[t-1]!=null&&!n[t-1].match(/\s/);)t--;return t}function Ye(n,e,t){let i=e,o=t?/\n/:/\s/;for(;n[i]&&!n[i].match(o);)i++;return i}function ce(n){let e=n.value.split(` -`),t=0;for(let i=0;i=t&&n.selectionStart=t&&n.selectionEnde in n?Ge(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,re=(n,e)=>{for(var t in e||(e={}))Ze.call(e,t)&&oe(n,t,e[t]);if(ne)for(var t of ne(e))Je.call(e,t)&&oe(n,t,e[t]);return n},_={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Xe(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function M(n){return re(re({},Xe()),n)}var V=!1;function Ye(){return V}function b(n,e,t){V&&(console.group(`\u{1F50D} ${n}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function F(n,e){if(!V)return;let t=n.value.slice(n.selectionStart,n.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let i=n.value.slice(Math.max(0,n.selectionStart-10),n.selectionStart),o=n.value.slice(n.selectionEnd,Math.min(n.value.length,n.selectionEnd+10));console.log("Context:",JSON.stringify(i)+"[SELECTION]"+JSON.stringify(o)),console.groupEnd()}function ce(n){V&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(n.text)),console.log("New selection:",`${n.selectionStart}-${n.selectionEnd}`),console.groupEnd())}var H=null;function I(n,{text:e,selectionStart:t,selectionEnd:i}){let o=Ye();o&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",i)),n.focus();let r=n.selectionStart,s=n.selectionEnd,a=n.value.slice(0,r),c=n.value.slice(s);o&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(n.value.slice(r,s))));let d=n.value,l=r!==s;if(H===null||H===!0){n.contentEditable="true";try{H=document.execCommand("insertText",!1,e),o&&console.log("execCommand returned:",H,"for text with",e.split(` +`).length,"lines")}catch(p){H=!1,o&&console.log("execCommand threw error:",p)}n.contentEditable="false"}if(o&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let p=a+e+c,h=n.value;o&&(console.log("Expected length:",p.length),console.log("Actual length:",h.length)),h!==p&&o&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(p.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!H)if(o&&console.log("Using manual insertion"),n.value===d){o&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(p){}n.value=a+e+c;try{document.execCommand("ms-endUndoUnit")}catch(p){}n.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else o&&console.log("Value was changed by execCommand, skipping manual insertion");o&&console.log("Setting selection range:",t,i),t!=null&&i!=null?n.setSelectionRange(t,i):n.setSelectionRange(r,n.selectionEnd),o&&(console.log("Final value length:",n.value.length),console.groupEnd())}function se(n){return n.trim().split(` +`).length>1}function et(n,e){let t=e;for(;n[t]&&n[t-1]!=null&&!n[t-1].match(/\s/);)t--;return t}function tt(n,e,t){let i=e,o=t?/\n/:/\s/;for(;n[i]&&!n[i].match(o);)i++;return i}function pe(n){let e=n.value.split(` +`),t=0;for(let i=0;i=t&&n.selectionStart=t&&n.selectionEnd0&&s[a-1]!==` `;)a--;if(r){let d=i;for(;d0?`${s} -`:o,v=re(m)&&a&&a.length>0?` -${a}`:r;if(d){let S=n.value[n.selectionStart-1];n.selectionStart!==0&&S!=null&&!S.match(/\s/)&&(g=` ${g}`)}m=et(n,g,v,e.multiline);let b=n.selectionStart,x=n.selectionEnd,$=c&&c.length>0&&v.indexOf(c)>-1&&m.length>0;if(p){let S=Z(n);t=S.newlinesToAppend,i=S.newlinesToPrepend,g=t+o,v+=i}if(m.startsWith(g)&&m.endsWith(v)){let S=m.slice(g.length,m.length-v.length);if(u===f){let C=u-g.length;C=Math.max(C,b),C=Math.min(C,b+S.length),b=x=C}else x=b+S.length;return{text:S,selectionStart:b,selectionEnd:x}}else if($)if(l&&l.length>0&&m.match(l)){v=v.replace(c,m);let S=g+v;return b=x=b+g.length,{text:S,selectionStart:b,selectionEnd:x}}else{let S=g+m+v;return b=b+g.length+m.length+v.indexOf(c),x=b+c.length,{text:S,selectionStart:b,selectionEnd:x}}else{let S=g+m+v;b=u+g.length,x=f+g.length;let C=m.match(/^\s*|\s*$/g);if(h&&C){let Q=C[0]||"",X=C[1]||"";S=Q+g+m.trim()+v+X,b+=Q.length,x-=X.length}return{text:S,selectionStart:b,selectionEnd:x}}}function pe(n,e){let{prefix:t,suffix:i,surroundWithNewlines:o}=e,r=n.value.slice(n.selectionStart,n.selectionEnd),s=n.selectionStart,a=n.selectionEnd,c=r.split(` +`;)d++;n.selectionStart=a,n.selectionEnd=d}else pe(n);let c=e(n);if(t.adjustSelection){let l=n.value.slice(n.selectionStart,n.selectionEnd).startsWith(t.prefix),p=t.adjustSelection(l,i,o,a);c.selectionStart=p.start,c.selectionEnd=p.end}else if(t.prefix){let l=n.value.slice(n.selectionStart,n.selectionEnd).startsWith(t.prefix);r?l?(c.selectionStart=Math.max(i-t.prefix.length,a),c.selectionEnd=c.selectionStart):(c.selectionStart=i+t.prefix.length,c.selectionEnd=c.selectionStart):l?(c.selectionStart=Math.max(i-t.prefix.length,a),c.selectionEnd=Math.max(o-t.prefix.length,a)):(c.selectionStart=i+t.prefix.length,c.selectionEnd=o+t.prefix.length)}return c}function D(n,e){let t,i,{prefix:o,suffix:r,blockPrefix:s,blockSuffix:a,replaceNext:c,prefixSpace:d,scanFor:l,surroundWithNewlines:p,trimFirst:h}=e,u=n.selectionStart,g=n.selectionEnd,f=n.value.slice(n.selectionStart,n.selectionEnd),v=se(f)&&s&&s.length>0?`${s} +`:o,y=se(f)&&a&&a.length>0?` +${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(v=` ${v}`)}f=it(n,v,y,e.multiline);let w=n.selectionStart,x=n.selectionEnd,$=c&&c.length>0&&y.indexOf(c)>-1&&f.length>0;if(p){let L=Z(n);t=L.newlinesToAppend,i=L.newlinesToPrepend,v=t+o,y+=i}if(f.startsWith(v)&&f.endsWith(y)){let L=f.slice(v.length,f.length-y.length);if(u===g){let C=u-v.length;C=Math.max(C,w),C=Math.min(C,w+L.length),w=x=C}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if($)if(l&&l.length>0&&f.match(l)){y=y.replace(c,f);let L=v+y;return w=x=w+v.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;return w=w+v.length+f.length+y.indexOf(c),x=w+c.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;w=u+v.length,x=g+v.length;let C=f.match(/^\s*|\s*$/g);if(h&&C){let Y=C[0]||"",ee=C[1]||"";L=Y+v+f.trim()+y+ee,w+=Y.length,x-=ee.length}return{text:L,selectionStart:w,selectionEnd:x}}}function de(n,e){let{prefix:t,suffix:i,surroundWithNewlines:o}=e,r=n.value.slice(n.selectionStart,n.selectionEnd),s=n.selectionStart,a=n.selectionEnd,c=r.split(` `);if(c.every(l=>l.startsWith(t)&&(!i||l.endsWith(i))))r=c.map(l=>{let p=l.slice(t.length);return i&&(p=p.slice(0,p.length-i.length)),p}).join(` `),a=s+r.length;else if(r=c.map(l=>t+l+(i||"")).join(` -`),o){let{newlinesToAppend:l,newlinesToPrepend:p}=Z(n);s+=l.length,a=s+r.length,r=l+r+p}return{text:r,selectionStart:s,selectionEnd:a}}function se(n){let e=n.split(` +`),o){let{newlinesToAppend:l,newlinesToPrepend:p}=Z(n);s+=l.length,a=s+r.length,r=l+r+p}return{text:r,selectionStart:s,selectionEnd:a}}function ae(n){let e=n.split(` `),t=/^\d+\.\s+/,i=e.every(r=>t.test(r)),o=e;return i&&(o=e.map(r=>r.replace(t,""))),{text:o.join(` -`),processed:i}}function ae(n){let e=n.split(` +`),processed:i}}function le(n){let e=n.split(` `),t="- ",i=e.every(r=>r.startsWith(t)),o=e;return i&&(o=e.map(r=>r.slice(t.length))),{text:o.join(` -`),processed:i}}function N(n,e){return e?"- ":`${n+1}. `}function tt(n,e){let t,i,o;return n.orderedList?(t=se(e),i=ae(t.text),o=i.text):(t=ae(e),i=se(t.text),o=i.text),[t,i,o]}function it(n,e){let t=n.selectionStart===n.selectionEnd,i=n.selectionStart,o=n.selectionEnd;ce(n);let r=n.value.slice(n.selectionStart,n.selectionEnd),[s,a,c]=tt(e,r),d=c.split(` -`).map((m,g)=>`${N(g,e.unorderedList)}${m}`),l=d.reduce((m,g,v)=>m+N(v,e.unorderedList).length,0),p=d.reduce((m,g,v)=>m+N(v,!e.unorderedList).length,0);if(s.processed)return t?(i=Math.max(i-N(0,e.unorderedList).length,0),o=i):(i=n.selectionStart,o=n.selectionEnd-l),{text:c,selectionStart:i,selectionEnd:o};let{newlinesToAppend:h,newlinesToPrepend:u}=Z(n),f=h+d.join(` -`)+u;return t?(i=Math.max(i+N(0,e.unorderedList).length+h.length,0),o=i):a.processed?(i=Math.max(n.selectionStart+h.length,0),o=n.selectionEnd+h.length+l-p):(i=Math.max(n.selectionStart+h.length,0),o=n.selectionEnd+h.length+l),{text:f,selectionStart:i,selectionEnd:o}}function de(n,e){let t=U(n,i=>it(i,e),{adjustSelection:(i,o,r,s)=>{let a=n.value.slice(s,n.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),h=e.orderedList&&l||e.unorderedList&&p;if(o===r)if(h){let u=a.match(e.orderedList?c:d),f=u?u[0].length:0;return{start:Math.max(o-f,s),end:Math.max(o-f,s)}}else if(l||p){let u=a.match(l?c:d),f=u?u[0].length:0,g=(e.unorderedList?2:3)-f;return{start:o+g,end:o+g}}else{let u=e.unorderedList?2:3;return{start:o+u,end:o+u}}else if(h){let u=a.match(e.orderedList?c:d),f=u?u[0].length:0;return{start:Math.max(o-f,s),end:Math.max(r-f,s)}}else if(l||p){let u=a.match(l?c:d),f=u?u[0].length:0,g=(e.unorderedList?2:3)-f;return{start:o+g,end:r+g}}else{let u=e.unorderedList?2:3;return{start:o+u,end:r+u}}}});I(n,t)}function nt(n){if(!n)return[];let e=[],{selectionStart:t,selectionEnd:i,value:o}=n,r=o.split(` -`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(o.length,i+10),l=o.slice(c,d);if(l.includes("**")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("**"),f=h.indexOf("**");u!==-1&&f!==-1&&e.push("bold")}if(l.includes("_")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("_"),f=h.indexOf("_");u!==-1&&f!==-1&&e.push("italic")}if(l.includes("`")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100));p.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("["),f=h.indexOf("]");u!==-1&&f!==-1&&o.slice(i+f+1,i+f+10).startsWith("(")&&e.push("link")}return e}function he(n){if(!n||n.disabled||n.readOnly)return;y("toggleBold","Starting"),R(n,"Before");let e=H(_.bold),t=D(n,e);le(t),I(n,t),R(n,"After")}function ue(n){if(!n||n.disabled||n.readOnly)return;let e=H(_.italic),t=D(n,e);I(n,t)}function me(n){if(!n||n.disabled||n.readOnly)return;let e=H(_.code),t=D(n,e);I(n,t)}function fe(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),i=H(_.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(i.suffix=`](${t})`,i.replaceNext=""):e.url&&(i.suffix=`](${e.url})`,i.replaceNext=""),e.text&&!t){let s=n.selectionStart;n.value=n.value.slice(0,s)+e.text+n.value.slice(s),n.selectionStart=s,n.selectionEnd=s+e.text.length}let r=D(n,i);I(n,r)}function ge(n){if(!n||n.disabled||n.readOnly)return;let e=H(_.bulletList);de(n,e)}function ve(n){if(!n||n.disabled||n.readOnly)return;let e=H(_.numberedList);de(n,e)}function ye(n){if(!n||n.disabled||n.readOnly)return;y("toggleQuote","Starting"),R(n,"Initial");let e=H(_.quote),t=U(n,i=>pe(i,e),{prefix:e.prefix});le(t),I(n,t),R(n,"Final")}function J(n){if(!n||n.disabled||n.readOnly)return;let e=H(_.taskList),t=U(n,i=>pe(i,e),{prefix:e.prefix});I(n,t)}function G(n,e=1,t=!1){if(!n||n.disabled||n.readOnly)return;(e<1||e>6)&&(e=1),y("insertHeader","============ START ============"),y("insertHeader",`Level: ${e}, Toggle: ${t}`),y("insertHeader",`Initial cursor: ${n.selectionStart}-${n.selectionEnd}`);let i=`header${e===1?"1":e}`,o=H(_[i]||_.header1);y("insertHeader",`Style prefix: "${o.prefix}"`);let r=n.value,s=n.selectionStart,a=n.selectionEnd,c=s;for(;c>0&&r[c-1]!==` +`),processed:i}}function O(n,e){return e?"- ":`${n+1}. `}function nt(n,e){let t,i,o;return n.orderedList?(t=ae(e),i=le(t.text),o=i.text):(t=le(e),i=ae(t.text),o=i.text),[t,i,o]}function ot(n,e){let t=n.selectionStart===n.selectionEnd,i=n.selectionStart,o=n.selectionEnd;pe(n);let r=n.value.slice(n.selectionStart,n.selectionEnd),[s,a,c]=nt(e,r),d=c.split(` +`).map((f,v)=>`${O(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+O(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+O(y,!e.unorderedList).length,0);if(s.processed)return t?(i=Math.max(i-O(0,e.unorderedList).length,0),o=i):(i=n.selectionStart,o=n.selectionEnd-l),{text:c,selectionStart:i,selectionEnd:o};let{newlinesToAppend:h,newlinesToPrepend:u}=Z(n),g=h+d.join(` +`)+u;return t?(i=Math.max(i+O(0,e.unorderedList).length+h.length,0),o=i):a.processed?(i=Math.max(n.selectionStart+h.length,0),o=n.selectionEnd+h.length+l-p):(i=Math.max(n.selectionStart+h.length,0),o=n.selectionEnd+h.length+l),{text:g,selectionStart:i,selectionEnd:o}}function he(n,e){let t=U(n,i=>ot(i,e),{adjustSelection:(i,o,r,s)=>{let a=n.value.slice(s,n.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),h=e.orderedList&&l||e.unorderedList&&p;if(o===r)if(h){let u=a.match(e.orderedList?c:d),g=u?u[0].length:0;return{start:Math.max(o-g,s),end:Math.max(o-g,s)}}else if(l||p){let u=a.match(l?c:d),g=u?u[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:o+v}}else{let u=e.unorderedList?2:3;return{start:o+u,end:o+u}}else if(h){let u=a.match(e.orderedList?c:d),g=u?u[0].length:0;return{start:Math.max(o-g,s),end:Math.max(r-g,s)}}else if(l||p){let u=a.match(l?c:d),g=u?u[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:r+v}}else{let u=e.unorderedList?2:3;return{start:o+u,end:r+u}}}});I(n,t)}function rt(n){if(!n)return[];let e=[],{selectionStart:t,selectionEnd:i,value:o}=n,r=o.split(` +`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(o.length,i+10),l=o.slice(c,d);if(l.includes("**")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("**"),g=h.indexOf("**");u!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("_"),g=h.indexOf("_");u!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100));p.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("["),g=h.indexOf("]");u!==-1&&g!==-1&&o.slice(i+g+1,i+g+10).startsWith("(")&&e.push("link")}return e}function ue(n){if(!n||n.disabled||n.readOnly)return;b("toggleBold","Starting"),F(n,"Before");let e=M(_.bold),t=D(n,e);ce(t),I(n,t),F(n,"After")}function me(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.italic),t=D(n,e);I(n,t)}function fe(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.code),t=D(n,e);I(n,t)}function ge(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),i=M(_.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(i.suffix=`](${t})`,i.replaceNext=""):e.url&&(i.suffix=`](${e.url})`,i.replaceNext=""),e.text&&!t){let s=n.selectionStart;n.value=n.value.slice(0,s)+e.text+n.value.slice(s),n.selectionStart=s,n.selectionEnd=s+e.text.length}let r=D(n,i);I(n,r)}function ve(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.bulletList);he(n,e)}function ye(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.numberedList);he(n,e)}function be(n){if(!n||n.disabled||n.readOnly)return;b("toggleQuote","Starting"),F(n,"Initial");let e=M(_.quote),t=U(n,i=>de(i,e),{prefix:e.prefix});ce(t),I(n,t),F(n,"Final")}function J(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.taskList),t=U(n,i=>de(i,e),{prefix:e.prefix});I(n,t)}function X(n,e=1,t=!1){if(!n||n.disabled||n.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${n.selectionStart}-${n.selectionEnd}`);let i=`header${e===1?"1":e}`,o=M(_[i]||_.header1);b("insertHeader",`Style prefix: "${o.prefix}"`);let r=n.value,s=n.selectionStart,a=n.selectionEnd,c=s;for(;c>0&&r[c-1]!==` `;)c--;let d=a;for(;d{let v=g.value.slice(g.selectionStart,g.selectionEnd);y("insertHeader",`Line in operation: "${v}"`);let b=v.replace(/^#{1,6}\s*/,"");y("insertHeader",`Cleaned line: "${b}"`);let x;return f?(y("insertHeader","ACTION: Toggling OFF - removing header"),x=b):h>0?(y("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=o.prefix+b):(y("insertHeader","ACTION: Adding new header"),x=o.prefix+b),y("insertHeader",`New line: "${x}"`),{text:x,selectionStart:g.selectionStart,selectionEnd:g.selectionEnd}},{prefix:o.prefix,adjustSelection:(g,v,b,x)=>{if(y("insertHeader","Adjusting selection:"),y("insertHeader",` - isRemoving param: ${g}`),y("insertHeader",` - shouldToggleOff: ${f}`),y("insertHeader",` - selStart: ${v}, selEnd: ${b}`),y("insertHeader",` - lineStartPos: ${x}`),f){let $=Math.max(v-u,x);return y("insertHeader",` - Removing header, adjusting by -${u}`),{start:$,end:v===b?$:Math.max(b-u,x)}}else if(u>0){let $=o.prefix.length-u;return y("insertHeader",` - Replacing header, adjusting by ${$}`),{start:v+$,end:b+$}}else return y("insertHeader",` - Adding header, adjusting by +${o.prefix.length}`),{start:v+o.prefix.length,end:b+o.prefix.length}}});y("insertHeader",`Final result: text="${m.text}", cursor=${m.selectionStart}-${m.selectionEnd}`),y("insertHeader","============ END ============"),I(n,m)}function be(n){G(n,1,!0)}function we(n){G(n,2,!0)}function xe(n){G(n,3,!0)}function ke(n){return nt(n)}var q=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",i=>{i.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=i=>{i.preventDefault();let o=e.actionId||e.name;this.editor.performAction(o,i)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let i=this.createViewModeDropdown(e),o=e.getBoundingClientRect();i.style.position="absolute",i.style.top=`${o.bottom+5}px`,i.style.left=`${o.left}px`,document.body.appendChild(i),this.handleDocumentClick=r=>{!i.contains(r.target)&&!e.contains(r.target)&&(i.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let i=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],o=this.editor.container.dataset.mode||"normal";return i.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===o){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=ke)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([i,o])=>{if(i==="viewMode")return;let r=!1;switch(i){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}o.classList.toggle("active",r),o.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:i,offset:o,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:i,offset:o,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` +`;)d++;let l=r.slice(c,d);b("insertHeader",`Current line (before): "${l}"`);let p=l.match(/^(#{1,6})\s*/),h=p?p[1].length:0,u=p?p[0].length:0;b("insertHeader","Existing header check:"),b("insertHeader",` - Match: ${p?`"${p[0]}"`:"none"}`),b("insertHeader",` - Existing level: ${h}`),b("insertHeader",` - Existing prefix length: ${u}`),b("insertHeader",` - Target level: ${e}`);let g=t&&h===e;b("insertHeader",`Should toggle OFF: ${g} (toggle=${t}, existingLevel=${h}, level=${e})`);let f=U(n,v=>{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):h>0?(b("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=o.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=o.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:o.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let $=Math.max(y-u,x);return b("insertHeader",` - Removing header, adjusting by -${u}`),{start:$,end:y===w?$:Math.max(w-u,x)}}else if(u>0){let $=o.prefix.length-u;return b("insertHeader",` - Replacing header, adjusting by ${$}`),{start:y+$,end:w+$}}else return b("insertHeader",` - Adding header, adjusting by +${o.prefix.length}`),{start:y+o.prefix.length,end:w+o.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),I(n,f)}function we(n){X(n,1,!0)}function xe(n){X(n,2,!0)}function ke(n){X(n,3,!0)}function Le(n){return rt(n)}var q=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",i=>{i.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=i=>{i.preventDefault();let o=e.actionId||e.name;this.editor.performAction(o,i)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let i=this.createViewModeDropdown(e),o=e.getBoundingClientRect();i.style.position="absolute",i.style.top=`${o.bottom+5}px`,i.style.left=`${o.left}px`,document.body.appendChild(i),this.handleDocumentClick=r=>{!i.contains(r.target)&&!e.contains(r.target)&&(i.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let i=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],o=this.editor.container.dataset.mode||"normal";return i.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===o){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Le)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([i,o])=>{if(i==="viewMode")return;let r=!1;switch(i){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}o.classList.toggle("active",r),o.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:i,offset:o,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:i,offset:o,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` @@ -890,7 +890,7 @@ ${a}`:r;if(d){let S=n.value[n.selectionStart-1];n.selectionStart!==0&&S!=null&&! - `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,i=this.findLinkAtPosition(t,e);i?(!this.currentLink||this.currentLink.url!==i.url||this.currentLink.index!==i.index)&&this.show(i):this.scheduleHide()}findLinkAtPosition(e,t){let i=/\[([^\]]+)\]\(([^)]+)\)/g,o,r=0;for(;(o=i.exec(e))!==null;){let s=o.index,a=o.index+o[0].length;if(t>=s&&t<=a)return{text:o[1],url:o[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let i=t.getBoundingClientRect();if(!(i.width===0||i.height===0))try{let{x:o,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${o}px`,top:`${r}px`,position:"absolute"})}catch(o){console.warn("Floating UI positioning failed:",o);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Le=` + `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,i=this.findLinkAtPosition(t,e);i?(!this.currentLink||this.currentLink.url!==i.url||this.currentLink.index!==i.index)&&this.show(i):this.scheduleHide()}findLinkAtPosition(e,t){let i=/\[([^\]]+)\]\(([^)]+)\)/g,o,r=0;for(;(o=i.exec(e))!==null;){let s=o.index,a=o.index+o[0].length;if(t>=s&&t<=a)return{text:o[1],url:o[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let i=t.getBoundingClientRect();if(!(i.width===0||i.height===0))try{let{x:o,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${o}px`,top:`${r}px`,position:"absolute"})}catch(o){console.warn("Floating UI positioning failed:",o);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Te=` `,Ee=` @@ -901,13 +901,13 @@ ${a}`:r;if(d){let S=n.value[n.selectionStart-1];n.selectionStart!==0&&S!=null&&! `,Ce=` -`,Te=` - `,Ae=` + +`,He=` -`,He=` +`,Me=` @@ -918,7 +918,7 @@ ${a}`:r;if(d){let S=n.value[n.selectionStart-1];n.selectionStart!==0&&S!=null&&! -`,Me=` +`,Ie=` @@ -926,29 +926,29 @@ ${a}`:r;if(d){let S=n.value[n.selectionStart-1];n.selectionStart!==0&&S!=null&&! -`,Ie=` +`,Pe=` -`,Pe=` +`,Be=` -`,Be=` +`,ze=` -`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Le,title:"Bold (Ctrl+B)",action:({editor:n})=>{he(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Ee,title:"Italic (Ctrl+I)",action:({editor:n})=>{ue(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:He,title:"Inline Code",action:({editor:n})=>{me(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:Ae,title:"Insert Link",action:({editor:n})=>{fe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:_e,title:"Heading 1",action:({editor:n})=>{be(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ce,title:"Heading 2",action:({editor:n})=>{we(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Te,title:"Heading 3",action:({editor:n})=>{xe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:n})=>{ge(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Me,title:"Numbered List",action:({editor:n})=>{ve(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:Pe,title:"Task List",action:({editor:n})=>{J&&(J(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Ie,title:"Quote",action:({editor:n})=>{ye(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Be,title:"View mode"}},O=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function ze(n){let e={};return(n||[]).forEach(t=>{if(!t||t.name==="separator")return;let i=t.actionId||t.name;t.action&&(e[i]=t.action)}),e}function Ne(n){let e=n||O;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function rt(n,e){let t=Ne(n),i=Ne(e);if(t===null||i===null)return t!==i;if(t.length!==i.length)return!0;for(let o=0;o{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(w.prototype);return s._init(r,t),r.overTypeInstance=s,w.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.options=this._mergeOptions(t),this.instanceId=++w.instanceCount,this.initialized=!1,w.injectStyles(),w.initGlobalListeners();let i=e.querySelector(".overtype-container"),o=e.querySelector(".overtype-wrapper");i||o?this._recoverFromDOM(i,o):this._buildFromScratch(),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:i,colors:o,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let i=this.instanceTheme||w.currentTheme||M,o=typeof i=="string"?i:i.name;if(o&&this.container.setAttribute("data-theme",o),this.instanceTheme){let r=typeof this.instanceTheme=="string"?T(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=B(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||w.currentTheme||M,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let i=typeof this.instanceTheme=="string"?T(this.instanceTheme):this.instanceTheme;if(i&&i.colors){let o=B(i.colors);this.container.style.cssText+=o}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([i,o])=>{i==="className"||i==="class"?this.textarea.className+=" "+o:i==="style"&&typeof o=="object"?Object.assign(this.textarea.style,o):this.textarea.setAttribute(i,o)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||O;this.toolbar=new q(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=ze(O),this.options.toolbarButtons&&Object.assign(this.actionsById,ze(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,i=this._getCurrentLine(e,t),o=this.container.dataset.mode==="preview",r=L.parse(e,i,this.options.showActiveLineRaw,this.options.codeHighlighter,o);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;t`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Te,title:"Bold (Ctrl+B)",action:({editor:n})=>{ue(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Ee,title:"Italic (Ctrl+I)",action:({editor:n})=>{me(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:Me,title:"Inline Code",action:({editor:n})=>{fe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:n})=>{ge(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:_e,title:"Heading 1",action:({editor:n})=>{we(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ce,title:"Heading 2",action:({editor:n})=>{xe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Ae,title:"Heading 3",action:({editor:n})=>{ke(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:n})=>{ve(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Ie,title:"Numbered List",action:({editor:n})=>{ye(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:Be,title:"Task List",action:({editor:n})=>{J&&(J(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:n})=>{be(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:ze,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function Oe(n){let e={};return(n||[]).forEach(t=>{if(!t||t.name==="separator")return;let i=t.actionId||t.name;t.action&&(e[i]=t.action)}),e}function Ne(n){let e=n||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function at(n,e){let t=Ne(n),i=Ne(e);if(t===null||i===null)return t!==i;if(t.length!==i.length)return!0;for(let o=0;o{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(m.prototype);return s._init(r,t),r.overTypeInstance=s,m.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++m.instanceCount,this.initialized=!1,m.injectStyles(),m.initGlobalListeners();let i=e.querySelector(".overtype-container"),o=e.querySelector(".overtype-wrapper");i||o?this._recoverFromDOM(i,o):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:i,colors:o,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let i=this.instanceTheme||m.currentTheme||A,o=typeof i=="string"?i:i.name;if(o&&this.container.setAttribute("data-theme",o),this.instanceTheme){let r=typeof this.instanceTheme=="string"?E(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=B(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||m.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let i=typeof this.instanceTheme=="string"?E(this.instanceTheme):this.instanceTheme;if(i&&i.colors){let o=B(i.colors);this.container.style.cssText+=o}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([i,o])=>{i==="className"||i==="class"?this.textarea.className+=" "+o:i==="style"&&typeof o=="object"?Object.assign(this.textarea.style,o):this.textarea.setAttribute(i,o)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new q(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=Oe(N),this.options.toolbarButtons&&Object.assign(this.actionsById,Oe(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,i=this._getCurrentLine(e,t),o=this.container.dataset.mode==="preview",r=S.parse(e,i,this.options.showActiveLineRaw,this.options.codeHighlighter,o);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tp.replace(/^ /,"")).join(` `);document.execCommand?(this.textarea.setSelectionRange(i,o),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=i,this.textarea.selectionEnd=i+l.length)}else if(i!==o){let s=r.substring(0,i),a=r.substring(i,o),c=r.substring(o),l=a.split(` `).map(p=>" "+p).join(` -`);document.execCommand?(this.textarea.setSelectionRange(i,o),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=i,this.textarea.selectionEnd=i+l.length)}else document.execCommand?document.execCommand("insertText",!1," "):(this.textarea.value=r.substring(0,i)+" "+r.substring(o),this.textarea.selectionStart=this.textarea.selectionEnd=i+2);this.textarea.dispatchEvent(new Event("input",{bubbles:!0}));return}if(e.key==="Enter"&&!e.shiftKey&&!e.metaKey&&!e.ctrlKey&&this.options.smartLists&&this.handleSmartListContinuation()){e.preventDefault();return}!this.shortcuts.handleKeydown(e)&&this.options.onKeydown&&this.options.onKeydown(e,this)}handleSmartListContinuation(){let e=this.textarea,t=e.selectionStart,i=L.getListContext(e.value,t);return!i||!i.inList?!1:i.content.trim()===""&&t>=i.markerEndPos?(this.deleteListMarker(i),!0):(t>i.markerEndPos&&t{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,i=L.renumberLists(e);if(i!==e){let o=0,r=e.split(` +`);document.execCommand?(this.textarea.setSelectionRange(i,o),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=i,this.textarea.selectionEnd=i+l.length)}else document.execCommand?document.execCommand("insertText",!1," "):(this.textarea.value=r.substring(0,i)+" "+r.substring(o),this.textarea.selectionStart=this.textarea.selectionEnd=i+2);this.textarea.dispatchEvent(new Event("input",{bubbles:!0}));return}if(e.key==="Enter"&&!e.shiftKey&&!e.metaKey&&!e.ctrlKey&&this.options.smartLists&&this.handleSmartListContinuation()){e.preventDefault();return}!this.shortcuts.handleKeydown(e)&&this.options.onKeydown&&this.options.onKeydown(e,this)}handleSmartListContinuation(){let e=this.textarea,t=e.selectionStart,i=S.getListContext(e.value,t);return!i||!i.inList?!1:i.content.trim()===""&&t>=i.markerEndPos?(this.deleteListMarker(i),!0):(t>i.markerEndPos&&t{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,i=S.renumberLists(e);if(i!==e){let o=0,r=e.split(` `),s=i.split(` -`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),i=L.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(i=i.replace(/.*?<\/span>/g,""),i=i.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),i=i.replace(/\sclass=""/g,"")),i}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var o;let t=(o=this.options)==null?void 0:o.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let i=this.toolbar&&this.options.toolbar&&rt(t,this.options.toolbarButtons);this._rebuildActionsMap(),i&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){this.instanceTheme=e;let t=typeof e=="string"?T(e):e,i=typeof t=="string"?t:t.name;if(i&&this.container.setAttribute("data-theme",i),t&&t.colors){let o=B(t.colors);this.container.style.cssText+=o}return this.updatePreview(),this}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` +`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),i=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(i=i.replace(/.*?<\/span>/g,""),i=i.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),i=i.replace(/\sclass=""/g,"")),i}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var o;let t=(o=this.options)==null?void 0:o.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let i=this.toolbar&&this.options.toolbar&&at(t,this.options.toolbarButtons);this._rebuildActionsMap(),i&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAutoThemeListener(),this.instanceTheme=e,e==="auto"){this._setupAutoThemeListener();let t=Q("auto");this._applyResolvedTheme(t)}else{let t=typeof e=="string"?E(e):e,i=typeof t=="string"?t:t.name;if(i&&this.container.setAttribute("data-theme",i),t&&t.colors){let o=B(t.colors);this.container.style.cssText+=o}this.updatePreview()}return this}_applyResolvedTheme(e){let t=E(e);if(this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t&&t.colors){let i=B(t.colors);this.container.style.cssText+=i}this.updatePreview()}_setupAutoThemeListener(){window.matchMedia&&(this.autoThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.autoThemeListener=e=>{let t=e.matches?"cave":"solar";this._applyResolvedTheme(t)},this.autoThemeMediaQuery.addEventListener?this.autoThemeMediaQuery.addEventListener("change",this.autoThemeListener):this.autoThemeMediaQuery.addListener&&this.autoThemeMediaQuery.addListener(this.autoThemeListener))}_cleanupAutoThemeListener(){this.autoThemeMediaQuery&&this.autoThemeListener&&(this.autoThemeMediaQuery.removeEventListener?this.autoThemeMediaQuery.removeEventListener("change",this.autoThemeListener):this.autoThemeMediaQuery.removeListener&&this.autoThemeMediaQuery.removeListener(this.autoThemeListener),this.autoThemeMediaQuery=null,this.autoThemeListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` `),i=e.length,o=e.split(/\s+/).filter(l=>l.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(` `),c=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:i,words:o,lines:t.length,line:c,column:d}):this.statsBar.innerHTML=`
    @@ -956,8 +956,8 @@ ${a}`:r;if(d){let S=n.value[n.selectionStart-1];n.selectionStart!==0&&S!=null&&! ${i} chars, ${o} words, ${t.length} lines
    Line ${c}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper,o=window.getComputedStyle(e),r=parseFloat(o.paddingTop),s=parseFloat(o.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this.element.overTypeInstance=null,w.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new w(e,t)}static initFromData(e,t={}){let i=document.querySelectorAll(e);return Array.from(i).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=w._parseDataValue(s.value)}return new w(o,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||w.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=w.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(w.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=w.currentTheme||M,o=F({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),w.stylesInjected=!0}static setTheme(e,t=null){let i=typeof e=="string"?T(e):e;t&&(i=te(i,t)),w.currentTheme=i,w.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(r=>{let s=typeof i=="string"?i:i.name;s&&r.setAttribute("data-theme",s)}),document.querySelectorAll(".overtype-wrapper").forEach(r=>{if(!r.closest(".overtype-container")){let a=typeof i=="string"?i:i.name;a&&r.setAttribute("data-theme",a)}let s=r._instance;s&&s.updatePreview()});let o=typeof i=="string"?i:i.name;document.querySelectorAll("overtype-editor").forEach(r=>{o&&typeof r.setAttribute=="function"&&r.setAttribute("theme",o),typeof r.refreshTheme=="function"&&r.refreshTheme()})}static setCodeHighlighter(e){L.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static setCustomSyntax(e){L.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static initGlobalListeners(){w.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let i=t.closest(".overtype-wrapper"),o=i==null?void 0:i._instance;o&&(o.options.showStats&&o.statsBar&&o._updateStats(),clearTimeout(o._selectionTimeout),o._selectionTimeout=setTimeout(()=>{o.updatePreview()},50))}}),w.globalListenersInitialized=!0)}};E(w,"instances",new WeakMap),E(w,"stylesInjected",!1),E(w,"globalListenersInitialized",!1),E(w,"instanceCount",0);var P=w;P.MarkdownParser=L;P.ShortcutsManager=z;P.themes={solar:M,cave:T("cave")};P.getTheme=T;P.currentTheme=M;var Oe=P;var je="overtype-webcomponent-container",st="Start typing...",at=["value","theme","toolbar","height","min-height","max-height","placeholder","font-size","line-height","padding","auto-resize","autofocus","show-stats","smart-lists","readonly"],K=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._editor=null,this._initialized=!1,this._pendingOptions={},this._styleVersion=0,this._baseStyleElement=null,this._selectionChangeHandler=null,this._isConnected=!1,this._handleChange=this._handleChange.bind(this),this._handleKeydown=this._handleKeydown.bind(this)}_decodeValue(e){return typeof e!="string"?"":e.replace(/\\r/g,"\r").replace(/\\n/g,` -`).replace(/\\t/g," ")}static get observedAttributes(){return at}connectedCallback(){this._isConnected=!0,this._initializeEditor()}disconnectedCallback(){this._isConnected=!1,this._cleanup()}attributeChangedCallback(e,t,i){if(t!==i&&!this._silentUpdate){if(!this._initialized){this._pendingOptions[e]=i;return}this._updateOption(e,i)}}_initializeEditor(){if(!(this._initialized||!this._isConnected))try{let e=document.createElement("div");e.className=je;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");t&&(e.style.height=t),i&&(e.style.minHeight=i),o&&(e.style.maxHeight=o),this._injectStyles(),this.shadowRoot.appendChild(e);let r=this._getOptionsFromAttributes(),s=new Oe(e,r);this._editor=s[0],this._initialized=!0,this._editor&&this._editor.textarea&&(this._editor.textarea.addEventListener("scroll",()=>{this._editor&&this._editor.preview&&this._editor.textarea&&(this._editor.preview.scrollTop=this._editor.textarea.scrollTop,this._editor.preview.scrollLeft=this._editor.textarea.scrollLeft)}),this._editor.textarea.addEventListener("input",a=>{this._editor&&this._editor.handleInput&&this._editor.handleInput(a)}),this._editor.textarea.addEventListener("keydown",a=>{this._editor&&this._editor.handleKeydown&&this._editor.handleKeydown(a)}),this._selectionChangeHandler=()=>{if(document.activeElement===this){let a=this.shadowRoot.activeElement;a&&a===this._editor.textarea&&(this._editor.options.showStats&&this._editor.statsBar&&this._editor._updateStats(),this._editor.linkTooltip&&this._editor.linkTooltip.checkCursorPosition&&this._editor.linkTooltip.checkCursorPosition())}},document.addEventListener("selectionchange",this._selectionChangeHandler)),this._applyPendingOptions(),this._dispatchEvent("ready",{editor:this._editor})}catch(e){let t=e&&e.message?e.message:String(e);console.warn("OverType Web Component initialization failed:",t),this._dispatchEvent("error",{error:{message:t}})}}_injectStyles(){let e=document.createElement("style"),t=this.getAttribute("theme")||"solar",i=T(t),o=this._getOptionsFromAttributes(),r=F({...o,theme:i}),s=` + `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper,o=window.getComputedStyle(e),r=parseFloat(o.paddingTop),s=parseFloat(o.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAutoThemeListener(),this.element.overTypeInstance=null,m.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new m(e,t)}static initFromData(e,t={}){let i=document.querySelectorAll(e);return Array.from(i).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=m._parseDataValue(s.value)}return new m(o,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||m.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=m.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(m.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=m.currentTheme||A,o=R({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),m.stylesInjected=!0}static setTheme(e,t=null){if(m._cleanupGlobalAutoThemeListener(),e==="auto"){m._setupGlobalAutoThemeListener();let i=Q("auto");m._applyGlobalResolvedTheme(i,t)}else{let i=typeof e=="string"?E(e):e;t&&(i=G(i,t)),m.currentTheme=i,m.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(r=>{let s=typeof i=="string"?i:i.name;s&&r.setAttribute("data-theme",s)}),document.querySelectorAll(".overtype-wrapper").forEach(r=>{if(!r.closest(".overtype-container")){let a=typeof i=="string"?i:i.name;a&&r.setAttribute("data-theme",a)}let s=r._instance;s&&s.updatePreview()});let o=typeof i=="string"?i:i.name;document.querySelectorAll("overtype-editor").forEach(r=>{o&&typeof r.setAttribute=="function"&&r.setAttribute("theme",o),typeof r.refreshTheme=="function"&&r.refreshTheme()})}}static _applyGlobalResolvedTheme(e,t=null){let i=E(e);t&&(i=G(i,t)),m.currentTheme=i,m.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(o=>{o.setAttribute("data-theme","auto"),o.setAttribute("data-resolved-theme",e)}),document.querySelectorAll(".overtype-wrapper").forEach(o=>{o.closest(".overtype-container")||(o.setAttribute("data-theme","auto"),o.setAttribute("data-resolved-theme",e));let r=o._instance;r&&r.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(o=>{typeof o.setAttribute=="function"&&(o.setAttribute("theme","auto"),o.setAttribute("data-resolved-theme",e)),typeof o.refreshTheme=="function"&&o.refreshTheme()})}static _setupGlobalAutoThemeListener(){window.matchMedia&&(m.autoThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),m.autoThemeListener=e=>{let t=e.matches?"cave":"solar";m._applyGlobalResolvedTheme(t)},m.autoThemeMediaQuery.addEventListener?m.autoThemeMediaQuery.addEventListener("change",m.autoThemeListener):m.autoThemeMediaQuery.addListener&&m.autoThemeMediaQuery.addListener(m.autoThemeListener))}static _cleanupGlobalAutoThemeListener(){m.autoThemeMediaQuery&&m.autoThemeListener&&(m.autoThemeMediaQuery.removeEventListener?m.autoThemeMediaQuery.removeEventListener("change",m.autoThemeListener):m.autoThemeMediaQuery.removeListener&&m.autoThemeMediaQuery.removeListener(m.autoThemeListener),m.autoThemeMediaQuery=null,m.autoThemeListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static initGlobalListeners(){m.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let i=t.closest(".overtype-wrapper"),o=i==null?void 0:i._instance;o&&(o.options.showStats&&o.statsBar&&o._updateStats(),clearTimeout(o._selectionTimeout),o._selectionTimeout=setTimeout(()=>{o.updatePreview()},50))}}),m.globalListenersInitialized=!0)}};T(m,"instances",new WeakMap),T(m,"stylesInjected",!1),T(m,"globalListenersInitialized",!1),T(m,"instanceCount",0),T(m,"autoThemeMediaQuery",null),T(m,"autoThemeListener",null);var P=m;P.MarkdownParser=S;P.ShortcutsManager=z;P.themes={solar:A,cave:E("cave")};P.getTheme=E;P.currentTheme=A;var je=P;var Re="overtype-webcomponent-container",lt="Start typing...",ct=["value","theme","toolbar","height","min-height","max-height","placeholder","font-size","line-height","padding","auto-resize","autofocus","show-stats","smart-lists","readonly"],K=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._editor=null,this._initialized=!1,this._pendingOptions={},this._styleVersion=0,this._baseStyleElement=null,this._selectionChangeHandler=null,this._isConnected=!1,this._handleChange=this._handleChange.bind(this),this._handleKeydown=this._handleKeydown.bind(this)}_decodeValue(e){return typeof e!="string"?"":e.replace(/\\r/g,"\r").replace(/\\n/g,` +`).replace(/\\t/g," ")}static get observedAttributes(){return ct}connectedCallback(){this._isConnected=!0,this._initializeEditor()}disconnectedCallback(){this._isConnected=!1,this._cleanup()}attributeChangedCallback(e,t,i){if(t!==i&&!this._silentUpdate){if(!this._initialized){this._pendingOptions[e]=i;return}this._updateOption(e,i)}}_initializeEditor(){if(!(this._initialized||!this._isConnected))try{let e=document.createElement("div");e.className=Re;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");t&&(e.style.height=t),i&&(e.style.minHeight=i),o&&(e.style.maxHeight=o),this._injectStyles(),this.shadowRoot.appendChild(e);let r=this._getOptionsFromAttributes(),s=new je(e,r);this._editor=s[0],this._initialized=!0,this._editor&&this._editor.textarea&&(this._editor.textarea.addEventListener("scroll",()=>{this._editor&&this._editor.preview&&this._editor.textarea&&(this._editor.preview.scrollTop=this._editor.textarea.scrollTop,this._editor.preview.scrollLeft=this._editor.textarea.scrollLeft)}),this._editor.textarea.addEventListener("input",a=>{this._editor&&this._editor.handleInput&&this._editor.handleInput(a)}),this._editor.textarea.addEventListener("keydown",a=>{this._editor&&this._editor.handleKeydown&&this._editor.handleKeydown(a)}),this._selectionChangeHandler=()=>{if(document.activeElement===this){let a=this.shadowRoot.activeElement;a&&a===this._editor.textarea&&(this._editor.options.showStats&&this._editor.statsBar&&this._editor._updateStats(),this._editor.linkTooltip&&this._editor.linkTooltip.checkCursorPosition&&this._editor.linkTooltip.checkCursorPosition())}},document.addEventListener("selectionchange",this._selectionChangeHandler)),this._applyPendingOptions(),this._dispatchEvent("ready",{editor:this._editor})}catch(e){let t=e&&e.message?e.message:String(e);console.warn("OverType Web Component initialization failed:",t),this._dispatchEvent("error",{error:{message:t}})}}_injectStyles(){let e=document.createElement("style"),t=this.getAttribute("theme")||"solar",i=E(t),o=this._getOptionsFromAttributes(),r=R({...o,theme:i}),s=` /* Web Component Host Styles */ :host { display: block; @@ -979,9 +979,9 @@ ${a}`:r;if(d){let S=n.value[n.selectionStart-1];n.selectionStart!==0&&S!=null&&! } `;this._styleVersion+=1;let a=` /* overtype-webcomponent styles v${this._styleVersion} */ -`;e.textContent=a+r+s,this._baseStyleElement=e,this.shadowRoot.appendChild(e)}_getOptionsFromAttributes(){let e={value:this.getAttribute("value")!==null?this._decodeValue(this.getAttribute("value")):(this.textContent||"").trim(),placeholder:this.getAttribute("placeholder")||st,toolbar:this.hasAttribute("toolbar"),autofocus:this.hasAttribute("autofocus"),autoResize:this.hasAttribute("auto-resize"),showStats:this.hasAttribute("show-stats"),smartLists:!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false",onChange:this._handleChange,onKeydown:this._handleKeydown},t=this.getAttribute("font-size");t&&(e.fontSize=t);let i=this.getAttribute("line-height");i&&(e.lineHeight=parseFloat(i)||1.6);let o=this.getAttribute("padding");o&&(e.padding=o);let r=this.getAttribute("min-height");r&&(e.minHeight=r);let s=this.getAttribute("max-height");return s&&(e.maxHeight=s),e}_applyPendingOptions(){for(let[e,t]of Object.entries(this._pendingOptions))this._updateOption(e,t);this._pendingOptions={}}_updateOption(e,t){if(this._editor)switch(e){case"value":{let i=this._decodeValue(t);this._editor.getValue()!==i&&this._editor.setValue(i||"")}break;case"theme":this._reinjectStyles(),this._editor&&this._editor.setTheme&&this._editor.setTheme(t||"solar");break;case"placeholder":this._editor.textarea&&(this._editor.textarea.placeholder=t||"");break;case"readonly":this._editor.textarea&&(this._editor.textarea.readOnly=this.hasAttribute("readonly"));break;case"height":case"min-height":case"max-height":this._updateContainerHeight();break;case"toolbar":if(!!this.hasAttribute("toolbar")==!!this._editor.options.toolbar)return;this._reinitializeEditor();break;case"auto-resize":if(!!this.hasAttribute("auto-resize")==!!this._editor.options.autoResize)return;this._reinitializeEditor();break;case"show-stats":if(!!this.hasAttribute("show-stats")==!!this._editor.options.showStats)return;this._reinitializeEditor();break;case"font-size":{this._updateFontSize(t)&&this._reinjectStyles();break}case"line-height":{this._updateLineHeight(t)&&this._reinjectStyles();break}case"padding":this._reinjectStyles();break;case"smart-lists":{let i=!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false";if(!!this._editor.options.smartLists==!!i)return;this._reinitializeEditor();break}}}_updateContainerHeight(){let e=this.shadowRoot.querySelector(`.${je}`);if(!e)return;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");e.style.height=t||"",e.style.minHeight=i||"",e.style.maxHeight=o||""}_updateFontSize(e){return this._editor&&this._editor.wrapper?(this._editor.options.fontSize=e||"",this._editor.wrapper.style.setProperty("--instance-font-size",this._editor.options.fontSize),this._editor.updatePreview(),!0):!1}_updateLineHeight(e){if(this._editor&&this._editor.wrapper){let t=parseFloat(e),i=Number.isFinite(t)?t:this._editor.options.lineHeight;return this._editor.options.lineHeight=i,this._editor.wrapper.style.setProperty("--instance-line-height",String(i)),this._editor.updatePreview(),!0}return!1}_reinjectStyles(){this._baseStyleElement&&this._baseStyleElement.parentNode&&this._baseStyleElement.remove(),this._injectStyles()}_reinitializeEditor(){let e=this._editor?this._editor.getValue():"";this._cleanup(),this._initialized=!1,this.shadowRoot.innerHTML="",e&&!this.getAttribute("value")&&this.setAttribute("value",e),this._initializeEditor()}_handleChange(e){this._updateValueAttribute(e),!(!this._initialized||!this._editor)&&this._dispatchEvent("change",{value:e,editor:this._editor})}_handleKeydown(e){this._dispatchEvent("keydown",{event:e,editor:this._editor})}_updateValueAttribute(e){this.getAttribute("value")!==e&&(this._silentUpdate=!0,this.setAttribute("value",e),this._silentUpdate=!1)}_dispatchEvent(e,t={}){let i=new CustomEvent(e,{detail:t,bubbles:!0,composed:!0});this.dispatchEvent(i)}_cleanup(){this._selectionChangeHandler&&(document.removeEventListener("selectionchange",this._selectionChangeHandler),this._selectionChangeHandler=null),this._editor&&typeof this._editor.destroy=="function"&&this._editor.destroy(),this._editor=null,this._initialized=!1,this.shadowRoot&&(this.shadowRoot.innerHTML="")}refreshTheme(){this._initialized&&this._reinjectStyles()}getValue(){return this._editor?this._editor.getValue():this.getAttribute("value")||""}setValue(e){this._editor?this._editor.setValue(e):this.setAttribute("value",e)}getHTML(){return this._editor?this._editor.getRenderedHTML(!1):""}insertText(e){!this._editor||typeof e!="string"||this._editor.insertText(e)}focus(){this._editor&&this._editor.textarea&&this._editor.textarea.focus()}blur(){this._editor&&this._editor.textarea&&this._editor.textarea.blur()}getStats(){if(!this._editor||!this._editor.textarea)return null;let e=this._editor.textarea.value,t=e.split(` +`;e.textContent=a+r+s,this._baseStyleElement=e,this.shadowRoot.appendChild(e)}_getOptionsFromAttributes(){let e={value:this.getAttribute("value")!==null?this._decodeValue(this.getAttribute("value")):(this.textContent||"").trim(),placeholder:this.getAttribute("placeholder")||lt,toolbar:this.hasAttribute("toolbar"),autofocus:this.hasAttribute("autofocus"),autoResize:this.hasAttribute("auto-resize"),showStats:this.hasAttribute("show-stats"),smartLists:!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false",onChange:this._handleChange,onKeydown:this._handleKeydown},t=this.getAttribute("font-size");t&&(e.fontSize=t);let i=this.getAttribute("line-height");i&&(e.lineHeight=parseFloat(i)||1.6);let o=this.getAttribute("padding");o&&(e.padding=o);let r=this.getAttribute("min-height");r&&(e.minHeight=r);let s=this.getAttribute("max-height");return s&&(e.maxHeight=s),e}_applyPendingOptions(){for(let[e,t]of Object.entries(this._pendingOptions))this._updateOption(e,t);this._pendingOptions={}}_updateOption(e,t){if(this._editor)switch(e){case"value":{let i=this._decodeValue(t);this._editor.getValue()!==i&&this._editor.setValue(i||"")}break;case"theme":this._reinjectStyles(),this._editor&&this._editor.setTheme&&this._editor.setTheme(t||"solar");break;case"placeholder":this._editor.textarea&&(this._editor.textarea.placeholder=t||"");break;case"readonly":this._editor.textarea&&(this._editor.textarea.readOnly=this.hasAttribute("readonly"));break;case"height":case"min-height":case"max-height":this._updateContainerHeight();break;case"toolbar":if(!!this.hasAttribute("toolbar")==!!this._editor.options.toolbar)return;this._reinitializeEditor();break;case"auto-resize":if(!!this.hasAttribute("auto-resize")==!!this._editor.options.autoResize)return;this._reinitializeEditor();break;case"show-stats":if(!!this.hasAttribute("show-stats")==!!this._editor.options.showStats)return;this._reinitializeEditor();break;case"font-size":{this._updateFontSize(t)&&this._reinjectStyles();break}case"line-height":{this._updateLineHeight(t)&&this._reinjectStyles();break}case"padding":this._reinjectStyles();break;case"smart-lists":{let i=!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false";if(!!this._editor.options.smartLists==!!i)return;this._reinitializeEditor();break}}}_updateContainerHeight(){let e=this.shadowRoot.querySelector(`.${Re}`);if(!e)return;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");e.style.height=t||"",e.style.minHeight=i||"",e.style.maxHeight=o||""}_updateFontSize(e){return this._editor&&this._editor.wrapper?(this._editor.options.fontSize=e||"",this._editor.wrapper.style.setProperty("--instance-font-size",this._editor.options.fontSize),this._editor.updatePreview(),!0):!1}_updateLineHeight(e){if(this._editor&&this._editor.wrapper){let t=parseFloat(e),i=Number.isFinite(t)?t:this._editor.options.lineHeight;return this._editor.options.lineHeight=i,this._editor.wrapper.style.setProperty("--instance-line-height",String(i)),this._editor.updatePreview(),!0}return!1}_reinjectStyles(){this._baseStyleElement&&this._baseStyleElement.parentNode&&this._baseStyleElement.remove(),this._injectStyles()}_reinitializeEditor(){let e=this._editor?this._editor.getValue():"";this._cleanup(),this._initialized=!1,this.shadowRoot.innerHTML="",e&&!this.getAttribute("value")&&this.setAttribute("value",e),this._initializeEditor()}_handleChange(e){this._updateValueAttribute(e),!(!this._initialized||!this._editor)&&this._dispatchEvent("change",{value:e,editor:this._editor})}_handleKeydown(e){this._dispatchEvent("keydown",{event:e,editor:this._editor})}_updateValueAttribute(e){this.getAttribute("value")!==e&&(this._silentUpdate=!0,this.setAttribute("value",e),this._silentUpdate=!1)}_dispatchEvent(e,t={}){let i=new CustomEvent(e,{detail:t,bubbles:!0,composed:!0});this.dispatchEvent(i)}_cleanup(){this._selectionChangeHandler&&(document.removeEventListener("selectionchange",this._selectionChangeHandler),this._selectionChangeHandler=null),this._editor&&typeof this._editor.destroy=="function"&&this._editor.destroy(),this._editor=null,this._initialized=!1,this.shadowRoot&&(this.shadowRoot.innerHTML="")}refreshTheme(){this._initialized&&this._reinjectStyles()}getValue(){return this._editor?this._editor.getValue():this.getAttribute("value")||""}setValue(e){this._editor?this._editor.setValue(e):this.setAttribute("value",e)}getHTML(){return this._editor?this._editor.getRenderedHTML(!1):""}insertText(e){!this._editor||typeof e!="string"||this._editor.insertText(e)}focus(){this._editor&&this._editor.textarea&&this._editor.textarea.focus()}blur(){this._editor&&this._editor.textarea&&this._editor.textarea.blur()}getStats(){if(!this._editor||!this._editor.textarea)return null;let e=this._editor.textarea.value,t=e.split(` `),i=e.length,o=e.split(/\s+/).filter(l=>l.length>0).length,r=this._editor.textarea.selectionStart,a=e.substring(0,r).split(` -`),c=a.length,d=a[a.length-1].length+1;return{characters:i,words:o,lines:t.length,line:c,column:d}}isReady(){return this._initialized&&this._editor!==null}getEditor(){return this._editor}};customElements.get("overtype-editor")||customElements.define("overtype-editor",K);var lt=K;return We(ct);})(); +`),c=a.length,d=a[a.length-1].length+1;return{characters:i,words:o,lines:t.length,line:c,column:d}}isReady(){return this._initialized&&this._editor!==null}getEditor(){return this._editor}};customElements.get("overtype-editor")||customElements.define("overtype-editor",K);var pt=K;return Ke(dt);})(); /** * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment * @version 1.0.0 diff --git a/dist/overtype.cjs b/dist/overtype.cjs index e4d25dc..97069ea 100644 --- a/dist/overtype.cjs +++ b/dist/overtype.cjs @@ -1,5 +1,5 @@ /** - * OverType v2.1.0 + * OverType v2.1.1 * A lightweight markdown editor library with perfect WYSIWYG alignment * @license MIT * @author David Miranda @@ -940,9 +940,16 @@ var cave = { // Even lighter - active button background } }; +var auto = { + name: "auto", + // The auto theme doesn't have its own colors; it uses solar or cave dynamically + colors: solar.colors + // Default to solar colors for initial render +}; var themes = { solar, cave, + auto, // Aliases for backward compatibility light: solar, dark: cave @@ -954,6 +961,13 @@ function getTheme(theme) { } return theme; } +function resolveAutoTheme(themeName) { + if (themeName !== "auto") { + return themeName; + } + const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; + return isDarkMode ? "cave" : "solar"; +} function themeToCSSVars(colors) { const vars = []; for (const [key, value] of Object.entries(colors)) { @@ -3385,6 +3399,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { + // Listener function for auto theme changes /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -3428,6 +3443,8 @@ var _OverType = class _OverType { _init(element, options = {}) { this.element = element; this.instanceTheme = options.theme || null; + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; this.options = this._mergeOptions(options); this.instanceId = ++_OverType.instanceCount; this.initialized = false; @@ -3440,6 +3457,9 @@ var _OverType = class _OverType { } else { this._buildFromScratch(); } + if (this.instanceTheme) { + this.setTheme(this.instanceTheme); + } this.shortcuts = new ShortcutsManager(this); this._rebuildActionsMap(); this.linkTooltip = new LinkTooltip(this); @@ -4079,18 +4099,73 @@ var _OverType = class _OverType { * @returns {this} Returns this for chaining */ setTheme(theme) { + this._cleanupAutoThemeListener(); this.instanceTheme = theme; - const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName) { - this.container.setAttribute("data-theme", themeName); + if (theme === "auto") { + this._setupAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + this._applyResolvedTheme(resolvedTheme); + } else { + const themeObj = typeof theme === "string" ? getTheme(theme) : theme; + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName) { + this.container.setAttribute("data-theme", themeName); + } + if (themeObj && themeObj.colors) { + const cssVars = themeToCSSVars(themeObj.colors); + this.container.style.cssText += cssVars; + } + this.updatePreview(); } + return this; + } + /** + * Apply a resolved theme name (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + */ + _applyResolvedTheme(themeName) { + const themeObj = getTheme(themeName); + this.container.setAttribute("data-theme", "auto"); + this.container.setAttribute("data-resolved-theme", themeName); if (themeObj && themeObj.colors) { const cssVars = themeToCSSVars(themeObj.colors); this.container.style.cssText += cssVars; } this.updatePreview(); - return this; + } + /** + * Setup auto theme listener for instance + * @private + */ + _setupAutoThemeListener() { + if (!window.matchMedia) + return; + this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + this.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + this._applyResolvedTheme(resolvedTheme); + }; + if (this.autoThemeMediaQuery.addEventListener) { + this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.addListener) { + this.autoThemeMediaQuery.addListener(this.autoThemeListener); + } + } + /** + * Clean up auto theme listener for instance + * @private + */ + _cleanupAutoThemeListener() { + if (this.autoThemeMediaQuery && this.autoThemeListener) { + if (this.autoThemeMediaQuery.removeEventListener) { + this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.removeListener) { + this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + } + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; + } } /** * Set instance-specific code highlighter @@ -4244,6 +4319,7 @@ var _OverType = class _OverType { * Destroy the editor instance */ destroy() { + this._cleanupAutoThemeListener(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4349,40 +4425,117 @@ var _OverType = class _OverType { * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + _OverType._cleanupGlobalAutoThemeListener(); + if (theme === "auto") { + _OverType._setupGlobalAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + } else { + let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + if (customColors) { + themeObj = mergeTheme(themeObj, customColors); + } + _OverType.currentTheme = themeObj; + _OverType.injectStyles(true); + document.querySelectorAll(".overtype-container").forEach((container) => { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + container.setAttribute("data-theme", themeName2); + } + }); + document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { + if (!wrapper.closest(".overtype-container")) { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + wrapper.setAttribute("data-theme", themeName2); + } + } + const instance = wrapper._instance; + if (instance) { + instance.updatePreview(); + } + }); + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + document.querySelectorAll("overtype-editor").forEach((webComponent) => { + if (themeName && typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", themeName); + } + if (typeof webComponent.refreshTheme === "function") { + webComponent.refreshTheme(); + } + }); + } + } + /** + * Apply a resolved theme globally (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + * @param {Object} customColors - Optional color overrides + */ + static _applyGlobalResolvedTheme(themeName, customColors = null) { + let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } + container.setAttribute("data-theme", "auto"); + container.setAttribute("data-resolved-theme", themeName); }); document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); } const instance = wrapper._instance; if (instance) { instance.updatePreview(); } }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); + if (typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", "auto"); + webComponent.setAttribute("data-resolved-theme", themeName); } if (typeof webComponent.refreshTheme === "function") { webComponent.refreshTheme(); } }); } + /** + * Setup global auto theme listener + * @private + */ + static _setupGlobalAutoThemeListener() { + if (!window.matchMedia) + return; + _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + _OverType._applyGlobalResolvedTheme(resolvedTheme); + }; + if (_OverType.autoThemeMediaQuery.addEventListener) { + _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.addListener) { + _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + } + } + /** + * Clean up global auto theme listener + * @private + */ + static _cleanupGlobalAutoThemeListener() { + if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { + if (_OverType.autoThemeMediaQuery.removeEventListener) { + _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.removeListener) { + _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + } + _OverType.autoThemeMediaQuery = null; + _OverType.autoThemeListener = null; + } + } /** * Set global code highlighter for all OverType instances * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML @@ -4484,6 +4637,9 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); +__publicField(_OverType, "autoThemeMediaQuery", null); +// Media query for auto theme switching +__publicField(_OverType, "autoThemeListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype.esm.js b/dist/overtype.esm.js index 111fd09..9bb7d1a 100644 --- a/dist/overtype.esm.js +++ b/dist/overtype.esm.js @@ -1,5 +1,5 @@ /** - * OverType v2.1.0 + * OverType v2.1.1 * A lightweight markdown editor library with perfect WYSIWYG alignment * @license MIT * @author David Miranda @@ -914,9 +914,16 @@ var cave = { // Even lighter - active button background } }; +var auto = { + name: "auto", + // The auto theme doesn't have its own colors; it uses solar or cave dynamically + colors: solar.colors + // Default to solar colors for initial render +}; var themes = { solar, cave, + auto, // Aliases for backward compatibility light: solar, dark: cave @@ -928,6 +935,13 @@ function getTheme(theme) { } return theme; } +function resolveAutoTheme(themeName) { + if (themeName !== "auto") { + return themeName; + } + const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; + return isDarkMode ? "cave" : "solar"; +} function themeToCSSVars(colors) { const vars = []; for (const [key, value] of Object.entries(colors)) { @@ -3359,6 +3373,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { + // Listener function for auto theme changes /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -3402,6 +3417,8 @@ var _OverType = class _OverType { _init(element, options = {}) { this.element = element; this.instanceTheme = options.theme || null; + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; this.options = this._mergeOptions(options); this.instanceId = ++_OverType.instanceCount; this.initialized = false; @@ -3414,6 +3431,9 @@ var _OverType = class _OverType { } else { this._buildFromScratch(); } + if (this.instanceTheme) { + this.setTheme(this.instanceTheme); + } this.shortcuts = new ShortcutsManager(this); this._rebuildActionsMap(); this.linkTooltip = new LinkTooltip(this); @@ -4053,18 +4073,73 @@ var _OverType = class _OverType { * @returns {this} Returns this for chaining */ setTheme(theme) { + this._cleanupAutoThemeListener(); this.instanceTheme = theme; - const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName) { - this.container.setAttribute("data-theme", themeName); + if (theme === "auto") { + this._setupAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + this._applyResolvedTheme(resolvedTheme); + } else { + const themeObj = typeof theme === "string" ? getTheme(theme) : theme; + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName) { + this.container.setAttribute("data-theme", themeName); + } + if (themeObj && themeObj.colors) { + const cssVars = themeToCSSVars(themeObj.colors); + this.container.style.cssText += cssVars; + } + this.updatePreview(); } + return this; + } + /** + * Apply a resolved theme name (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + */ + _applyResolvedTheme(themeName) { + const themeObj = getTheme(themeName); + this.container.setAttribute("data-theme", "auto"); + this.container.setAttribute("data-resolved-theme", themeName); if (themeObj && themeObj.colors) { const cssVars = themeToCSSVars(themeObj.colors); this.container.style.cssText += cssVars; } this.updatePreview(); - return this; + } + /** + * Setup auto theme listener for instance + * @private + */ + _setupAutoThemeListener() { + if (!window.matchMedia) + return; + this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + this.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + this._applyResolvedTheme(resolvedTheme); + }; + if (this.autoThemeMediaQuery.addEventListener) { + this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.addListener) { + this.autoThemeMediaQuery.addListener(this.autoThemeListener); + } + } + /** + * Clean up auto theme listener for instance + * @private + */ + _cleanupAutoThemeListener() { + if (this.autoThemeMediaQuery && this.autoThemeListener) { + if (this.autoThemeMediaQuery.removeEventListener) { + this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.removeListener) { + this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + } + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; + } } /** * Set instance-specific code highlighter @@ -4218,6 +4293,7 @@ var _OverType = class _OverType { * Destroy the editor instance */ destroy() { + this._cleanupAutoThemeListener(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4323,40 +4399,117 @@ var _OverType = class _OverType { * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + _OverType._cleanupGlobalAutoThemeListener(); + if (theme === "auto") { + _OverType._setupGlobalAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + } else { + let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + if (customColors) { + themeObj = mergeTheme(themeObj, customColors); + } + _OverType.currentTheme = themeObj; + _OverType.injectStyles(true); + document.querySelectorAll(".overtype-container").forEach((container) => { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + container.setAttribute("data-theme", themeName2); + } + }); + document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { + if (!wrapper.closest(".overtype-container")) { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + wrapper.setAttribute("data-theme", themeName2); + } + } + const instance = wrapper._instance; + if (instance) { + instance.updatePreview(); + } + }); + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + document.querySelectorAll("overtype-editor").forEach((webComponent) => { + if (themeName && typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", themeName); + } + if (typeof webComponent.refreshTheme === "function") { + webComponent.refreshTheme(); + } + }); + } + } + /** + * Apply a resolved theme globally (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + * @param {Object} customColors - Optional color overrides + */ + static _applyGlobalResolvedTheme(themeName, customColors = null) { + let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } + container.setAttribute("data-theme", "auto"); + container.setAttribute("data-resolved-theme", themeName); }); document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); } const instance = wrapper._instance; if (instance) { instance.updatePreview(); } }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); + if (typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", "auto"); + webComponent.setAttribute("data-resolved-theme", themeName); } if (typeof webComponent.refreshTheme === "function") { webComponent.refreshTheme(); } }); } + /** + * Setup global auto theme listener + * @private + */ + static _setupGlobalAutoThemeListener() { + if (!window.matchMedia) + return; + _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + _OverType._applyGlobalResolvedTheme(resolvedTheme); + }; + if (_OverType.autoThemeMediaQuery.addEventListener) { + _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.addListener) { + _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + } + } + /** + * Clean up global auto theme listener + * @private + */ + static _cleanupGlobalAutoThemeListener() { + if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { + if (_OverType.autoThemeMediaQuery.removeEventListener) { + _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.removeListener) { + _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + } + _OverType.autoThemeMediaQuery = null; + _OverType.autoThemeListener = null; + } + } /** * Set global code highlighter for all OverType instances * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML @@ -4458,6 +4611,9 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); +__publicField(_OverType, "autoThemeMediaQuery", null); +// Media query for auto theme switching +__publicField(_OverType, "autoThemeListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype.esm.js.map b/dist/overtype.esm.js.map index b6a41cf..a591ee9 100644 --- a/dist/overtype.esm.js.map +++ b/dist/overtype.esm.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js", "../src/overtype.js"], - "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `[${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Get theme object\n      const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n      const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n      // Update container theme attribute\n      if (themeName) {\n        this.container.setAttribute('data-theme', themeName);\n      }\n\n      // Apply CSS variables to container for instance override\n      if (themeObj && themeObj.colors) {\n        const cssVars = themeToCSSVars(themeObj.colors);\n        this.container.style.cssText += cssVars;\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n\n      return this;\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances - update container theme attribute\n document.querySelectorAll('.overtype-container').forEach(container => {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n container.setAttribute('data-theme', themeName);\n }\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n // Set the theme attribute to update the theme name\n if (themeName && typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', themeName);\n }\n // Also call refreshTheme() to handle cases where the theme name stays the same\n // but the theme object's properties have changed\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], - "mappings": "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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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", + "sourcesContent": ["/**\r\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\r\n *\r\n * Key principles:\r\n * - Every character must occupy the exact same position as in the textarea\r\n * - No font-size changes, no padding/margin on inline elements\r\n * - Markdown tokens remain visible but styled\r\n */\r\nexport class MarkdownParser {\r\n // Track link index for anchor naming\r\n static linkIndex = 0;\r\n\r\n // Global code highlighter function\r\n static codeHighlighter = null;\r\n\r\n // Custom syntax processor function\r\n static customSyntax = null;\r\n\r\n /**\r\n * Reset link index (call before parsing a new document)\r\n */\r\n static resetLinkIndex() {\r\n this.linkIndex = 0;\r\n }\r\n\r\n /**\r\n * Set global code highlighter function\r\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n */\r\n static setCodeHighlighter(highlighter) {\r\n this.codeHighlighter = highlighter;\r\n }\r\n\r\n /**\r\n * Set custom syntax processor function\r\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\r\n */\r\n static setCustomSyntax(processor) {\r\n this.customSyntax = processor;\r\n }\r\n\r\n /**\r\n * Apply custom syntax processor to parsed HTML\r\n * @param {string} html - Parsed HTML line\r\n * @returns {string} HTML with custom syntax applied\r\n */\r\n static applyCustomSyntax(html) {\r\n if (this.customSyntax) {\r\n return this.customSyntax(html);\r\n }\r\n return html;\r\n }\r\n\r\n /**\r\n * Escape HTML special characters\r\n * @param {string} text - Raw text to escape\r\n * @returns {string} Escaped HTML-safe text\r\n */\r\n static escapeHtml(text) {\r\n const map = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": '''\r\n };\r\n return text.replace(/[&<>\"']/g, m => map[m]);\r\n }\r\n\r\n /**\r\n * Preserve leading spaces as non-breaking spaces\r\n * @param {string} html - HTML string\r\n * @param {string} originalLine - Original line with spaces\r\n * @returns {string} HTML with preserved indentation\r\n */\r\n static preserveIndentation(html, originalLine) {\r\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\r\n const indentation = leadingSpaces.replace(/ /g, ' ');\r\n return html.replace(/^\\s*/, indentation);\r\n }\r\n\r\n /**\r\n * Parse headers (h1-h3 only)\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed HTML with header styling\r\n */\r\n static parseHeader(html) {\r\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\r\n const level = hashes.length;\r\n return `${hashes} ${content}`;\r\n });\r\n }\r\n\r\n /**\r\n * Parse horizontal rules\r\n * @param {string} html - HTML line to parse\r\n * @returns {string|null} Parsed horizontal rule or null\r\n */\r\n static parseHorizontalRule(html) {\r\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\r\n return `
    ${html}
    `;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse blockquotes\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed blockquote\r\n */\r\n static parseBlockquote(html) {\r\n return html.replace(/^> (.+)$/, (match, content) => {\r\n return `> ${content}`;\r\n });\r\n }\r\n\r\n /**\r\n * Parse bullet lists\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed bullet list item\r\n */\r\n static parseBulletList(html) {\r\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\r\n return `${indent}
  • ${marker} ${content}
  • `;\r\n });\r\n }\r\n\r\n /**\r\n * Parse task lists (GitHub Flavored Markdown checkboxes)\r\n * @param {string} html - HTML line to parse\r\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\r\n * @returns {string} Parsed task list item\r\n */\r\n static parseTaskList(html, isPreviewMode = false) {\r\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\r\n if (isPreviewMode) {\r\n // Preview mode: render actual checkbox\r\n const isChecked = checked.toLowerCase() === 'x';\r\n return `${indent}
  • ${content}
  • `;\r\n } else {\r\n // Normal mode: keep syntax visible for alignment\r\n return `${indent}
  • - [${checked}] ${content}
  • `;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Parse numbered lists\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed numbered list item\r\n */\r\n static parseNumberedList(html) {\r\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\r\n return `${indent}
  • ${marker} ${content}
  • `;\r\n });\r\n }\r\n\r\n /**\r\n * Parse code blocks (markers only)\r\n * @param {string} html - HTML line to parse\r\n * @returns {string|null} Parsed code fence or null\r\n */\r\n static parseCodeBlock(html) {\r\n // The line must start with three backticks and have no backticks after subsequent text\r\n const codeFenceRegex = /^`{3}[^`]*$/;\r\n if (codeFenceRegex.test(html)) {\r\n return `
    ${html}
    `;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse bold text\r\n * @param {string} html - HTML with potential bold markdown\r\n * @returns {string} HTML with bold styling\r\n */\r\n static parseBold(html) {\r\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\r\n html = html.replace(/__(.+?)__/g, '__$1__');\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse italic text\r\n * Note: Uses lookbehind assertions - requires modern browsers\r\n * @param {string} html - HTML with potential italic markdown\r\n * @returns {string} HTML with italic styling\r\n */\r\n static parseItalic(html) {\r\n // Single asterisk - must not be adjacent to other asterisks\r\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\r\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\r\n\r\n // Single underscore - must be at word boundaries to avoid matching inside words\r\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\r\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\r\n\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse strikethrough text\r\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\r\n * @param {string} html - HTML with potential strikethrough markdown\r\n * @returns {string} HTML with strikethrough styling\r\n */\r\n static parseStrikethrough(html) {\r\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\r\n html = html.replace(/(?~~$1~~');\r\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\r\n html = html.replace(/(?~$1~');\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse inline code\r\n * @param {string} html - HTML with potential code markdown\r\n * @returns {string} HTML with code styling\r\n */\r\n static parseInlineCode(html) {\r\n // Must have equal number of backticks before and after inline code\r\n //\r\n // Regex explainer:\r\n // (?$1$2$3
    ');\r\n }\r\n\r\n /**\r\n * Sanitize URL to prevent XSS attacks\r\n * @param {string} url - URL to sanitize\r\n * @returns {string} Safe URL or '#' if dangerous\r\n */\r\n static sanitizeUrl(url) {\r\n // Trim whitespace and convert to lowercase for protocol check\r\n const trimmed = url.trim();\r\n const lower = trimmed.toLowerCase();\r\n\r\n // Allow safe protocols\r\n const safeProtocols = [\r\n 'http://',\r\n 'https://',\r\n 'mailto:',\r\n 'ftp://',\r\n 'ftps://'\r\n ];\r\n\r\n // Check if URL starts with a safe protocol\r\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\r\n\r\n // Allow relative URLs (starting with / or # or no protocol)\r\n const isRelative = trimmed.startsWith('/') ||\r\n trimmed.startsWith('#') ||\r\n trimmed.startsWith('?') ||\r\n trimmed.startsWith('.') ||\r\n (!trimmed.includes(':') && !trimmed.includes('//'));\r\n\r\n // If safe protocol or relative URL, return as-is\r\n if (hasSafeProtocol || isRelative) {\r\n return url;\r\n }\r\n\r\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\r\n return '#';\r\n }\r\n\r\n /**\r\n * Parse links\r\n * @param {string} html - HTML with potential link markdown\r\n * @returns {string} HTML with link styling\r\n */\r\n static parseLinks(html) {\r\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\r\n const anchorName = `--link-${this.linkIndex++}`;\r\n // Sanitize URL to prevent XSS attacks\r\n const safeUrl = this.sanitizeUrl(url);\r\n // Use real href - pointer-events handles click prevention in normal mode\r\n return `
    [${text}](${url})`;\r\n });\r\n }\r\n\r\n /**\r\n * Identify and protect sanctuaries (code and links) before parsing\r\n * @param {string} text - Text with potential markdown\r\n * @returns {Object} Object with protected text and sanctuary map\r\n */\r\n static identifyAndProtectSanctuaries(text) {\r\n const sanctuaries = new Map();\r\n let sanctuaryCounter = 0;\r\n let protectedText = text;\r\n \r\n // Create a map to track protected regions (URLs should not be processed)\r\n const protectedRegions = [];\r\n \r\n // First, find all links and mark their URL regions as protected\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n let linkMatch;\r\n while ((linkMatch = linkRegex.exec(text)) !== null) {\r\n // Calculate the exact position of the URL part\r\n // linkMatch.index is the start of the match\r\n // We need to find where \"](\" starts, then add 2 to get URL start\r\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\r\n const urlStart = bracketPos + 2;\r\n const urlEnd = urlStart + linkMatch[2].length;\r\n protectedRegions.push({ start: urlStart, end: urlEnd });\r\n }\r\n \r\n // Now protect inline code, but skip if it's inside a protected region (URL)\r\n const codeRegex = /(? \r\n codeStart >= region.start && codeEnd <= region.end\r\n );\r\n \r\n if (!inProtectedRegion) {\r\n codeMatches.push({\r\n match: codeMatch[0],\r\n index: codeMatch.index,\r\n openTicks: codeMatch[1],\r\n content: codeMatch[2],\r\n closeTicks: codeMatch[3]\r\n });\r\n }\r\n }\r\n \r\n // Replace code matches from end to start to preserve indices\r\n codeMatches.sort((a, b) => b.index - a.index);\r\n codeMatches.forEach(codeInfo => {\r\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\r\n sanctuaries.set(placeholder, {\r\n type: 'code',\r\n original: codeInfo.match,\r\n openTicks: codeInfo.openTicks,\r\n content: codeInfo.content,\r\n closeTicks: codeInfo.closeTicks\r\n });\r\n protectedText = protectedText.substring(0, codeInfo.index) + \r\n placeholder + \r\n protectedText.substring(codeInfo.index + codeInfo.match.length);\r\n });\r\n \r\n // Then protect links - they can contain sanctuary placeholders for code but not raw code\r\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\r\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\r\n sanctuaries.set(placeholder, {\r\n type: 'link',\r\n original: match,\r\n linkText,\r\n url\r\n });\r\n return placeholder;\r\n });\r\n \r\n return { protectedText, sanctuaries };\r\n }\r\n \r\n /**\r\n * Restore and transform sanctuaries back to HTML\r\n * @param {string} html - HTML with sanctuary placeholders\r\n * @param {Map} sanctuaries - Map of sanctuaries to restore\r\n * @returns {string} HTML with sanctuaries restored and transformed\r\n */\r\n static restoreAndTransformSanctuaries(html, sanctuaries) {\r\n // Sort sanctuary placeholders by position to restore in order\r\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\r\n const indexA = html.indexOf(a);\r\n const indexB = html.indexOf(b);\r\n return indexA - indexB;\r\n });\r\n \r\n placeholders.forEach(placeholder => {\r\n const sanctuary = sanctuaries.get(placeholder);\r\n let replacement;\r\n \r\n if (sanctuary.type === 'code') {\r\n // Transform code sanctuary to HTML\r\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\r\n } else if (sanctuary.type === 'link') {\r\n // For links, we need to process the link text for markdown\r\n let processedLinkText = sanctuary.linkText;\r\n \r\n // First restore any sanctuary placeholders that were already in the link text\r\n // (e.g., inline code that was protected before the link)\r\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\r\n if (processedLinkText.includes(innerPlaceholder)) {\r\n if (innerSanctuary.type === 'code') {\r\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\r\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\r\n }\r\n }\r\n });\r\n \r\n // Now parse other markdown in the link text (bold, italic, etc)\r\n processedLinkText = this.parseStrikethrough(processedLinkText);\r\n processedLinkText = this.parseBold(processedLinkText);\r\n processedLinkText = this.parseItalic(processedLinkText);\r\n \r\n // Transform link sanctuary to HTML\r\n // URL should NOT be processed for markdown - use it as-is\r\n const anchorName = `--link-${this.linkIndex++}`;\r\n const safeUrl = this.sanitizeUrl(sanctuary.url);\r\n replacement = `[${processedLinkText}](${sanctuary.url})`;\r\n }\r\n \r\n html = html.replace(placeholder, replacement);\r\n });\r\n \r\n return html;\r\n }\r\n \r\n /**\r\n * Parse all inline elements in correct order\r\n * @param {string} text - Text with potential inline markdown\r\n * @returns {string} HTML with all inline styling\r\n */\r\n static parseInlineElements(text) {\r\n // Step 1: Identify and protect sanctuaries (code and links)\r\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\r\n \r\n // Step 2: Parse other inline elements on protected text\r\n let html = protectedText;\r\n html = this.parseStrikethrough(html);\r\n html = this.parseBold(html);\r\n html = this.parseItalic(html);\r\n \r\n // Step 3: Restore and transform sanctuaries\r\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\r\n \r\n return html;\r\n }\r\n\r\n /**\r\n * Parse a single line of markdown\r\n * @param {string} line - Raw markdown line\r\n * @returns {string} Parsed HTML line\r\n */\r\n static parseLine(line, isPreviewMode = false) {\r\n let html = this.escapeHtml(line);\r\n\r\n // Preserve indentation\r\n html = this.preserveIndentation(html, line);\r\n\r\n // Check for block elements first\r\n const horizontalRule = this.parseHorizontalRule(html);\r\n if (horizontalRule) return horizontalRule;\r\n\r\n const codeBlock = this.parseCodeBlock(html);\r\n if (codeBlock) return codeBlock;\r\n\r\n // Parse block elements\r\n html = this.parseHeader(html);\r\n html = this.parseBlockquote(html);\r\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\r\n html = this.parseBulletList(html);\r\n html = this.parseNumberedList(html);\r\n\r\n // Parse inline elements\r\n html = this.parseInlineElements(html);\r\n\r\n // Wrap in div to maintain line structure\r\n if (html.trim() === '') {\r\n // Intentionally use   for empty lines to maintain vertical spacing\r\n // This causes a 0->1 character count difference but preserves visual alignment\r\n return '
     
    ';\r\n }\r\n\r\n return `
    ${html}
    `;\r\n }\r\n\r\n /**\r\n * Parse full markdown text\r\n * @param {string} text - Full markdown text\r\n * @param {number} activeLine - Currently active line index (optional)\r\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Parsed HTML\r\n */\r\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\r\n // Reset link counter for each parse\r\n this.resetLinkIndex();\r\n\r\n const lines = text.split('\\n');\r\n let inCodeBlock = false;\r\n\r\n const parsedLines = lines.map((line, index) => {\r\n // Show raw markdown on active line if requested\r\n if (showActiveLineRaw && index === activeLine) {\r\n const content = this.escapeHtml(line) || ' ';\r\n return `
    ${content}
    `;\r\n }\r\n\r\n // Check if this line is a code fence\r\n const codeFenceRegex = /^```[^`]*$/;\r\n if (codeFenceRegex.test(line)) {\r\n inCodeBlock = !inCodeBlock;\r\n // Parse fence markers normally to get styled output\r\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\r\n }\r\n\r\n // If we're inside a code block, don't parse as markdown\r\n if (inCodeBlock) {\r\n const escaped = this.escapeHtml(line);\r\n const indented = this.preserveIndentation(escaped, line);\r\n return `
    ${indented || ' '}
    `;\r\n }\r\n\r\n // Otherwise, parse the markdown normally\r\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\r\n });\r\n\r\n // Join without newlines to prevent extra spacing\r\n const html = parsedLines.join('');\r\n\r\n // Apply post-processing for list consolidation\r\n return this.postProcessHTML(html, instanceHighlighter);\r\n }\r\n\r\n /**\r\n * Post-process HTML to consolidate lists and code blocks\r\n * @param {string} html - HTML to post-process\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\r\n */\r\n static postProcessHTML(html, instanceHighlighter) {\r\n // Check if we're in a browser environment\r\n if (typeof document === 'undefined' || !document) {\r\n // In Node.js environment - do manual post-processing\r\n return this.postProcessHTMLManual(html, instanceHighlighter);\r\n }\r\n\r\n // Parse HTML string into DOM\r\n const container = document.createElement('div');\r\n container.innerHTML = html;\r\n\r\n let currentList = null;\r\n let listType = null;\r\n let currentCodeBlock = null;\r\n let inCodeBlock = false;\r\n\r\n // Process all direct children - need to be careful with live NodeList\r\n const children = Array.from(container.children);\r\n\r\n for (let i = 0; i < children.length; i++) {\r\n const child = children[i];\r\n\r\n // Skip if child was already processed/removed\r\n if (!child.parentNode) continue;\r\n\r\n // Check for code fence start/end\r\n const codeFence = child.querySelector('.code-fence');\r\n if (codeFence) {\r\n const fenceText = codeFence.textContent;\r\n if (fenceText.startsWith('```')) {\r\n if (!inCodeBlock) {\r\n // Start of code block - keep fence visible, then add pre/code\r\n inCodeBlock = true;\r\n\r\n // Create the code block that will follow the fence\r\n currentCodeBlock = document.createElement('pre');\r\n const codeElement = document.createElement('code');\r\n currentCodeBlock.appendChild(codeElement);\r\n currentCodeBlock.className = 'code-block';\r\n\r\n // Extract language if present\r\n const lang = fenceText.slice(3).trim();\r\n if (lang) {\r\n codeElement.className = `language-${lang}`;\r\n }\r\n\r\n // Insert code block after the fence div (don't remove the fence)\r\n container.insertBefore(currentCodeBlock, child.nextSibling);\r\n\r\n // Store reference to the code element for adding content\r\n currentCodeBlock._codeElement = codeElement;\r\n currentCodeBlock._language = lang;\r\n currentCodeBlock._codeContent = '';\r\n continue;\r\n } else {\r\n // End of code block - apply highlighting if needed\r\n // Use instance highlighter if provided, otherwise fall back to global highlighter\r\n const highlighter = instanceHighlighter || this.codeHighlighter;\r\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\r\n try {\r\n const result = highlighter(\r\n currentCodeBlock._codeContent,\r\n currentCodeBlock._language || ''\r\n );\r\n\r\n // Check if result is a Promise (async highlighter)\r\n if (result && typeof result.then === 'function') {\r\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\r\n // Keep the plain text fallback that was already set\r\n } else {\r\n // Synchronous highlighter\r\n // Verify highlighter returned non-empty string\r\n if (result && typeof result === 'string' && result.trim()) {\r\n currentCodeBlock._codeElement.innerHTML = result;\r\n }\r\n // else: keep the plain text fallback that was already set\r\n }\r\n } catch (error) {\r\n console.warn('Code highlighting failed:', error);\r\n // Keep the plain text content as fallback\r\n }\r\n }\r\n\r\n inCodeBlock = false;\r\n currentCodeBlock = null;\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n // Check if we're in a code block - any div that's not a code fence\r\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\r\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\r\n // Add the line content to the code block content (for highlighting)\r\n if (currentCodeBlock._codeContent.length > 0) {\r\n currentCodeBlock._codeContent += '\\n';\r\n }\r\n // Get the actual text content, preserving spaces\r\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\r\n currentCodeBlock._codeContent += lineText;\r\n\r\n // Also add to the code element (fallback if no highlighter)\r\n if (codeElement.textContent.length > 0) {\r\n codeElement.textContent += '\\n';\r\n }\r\n codeElement.textContent += lineText;\r\n child.remove();\r\n continue;\r\n }\r\n\r\n // Check if this div contains a list item\r\n let listItem = null;\r\n if (child.tagName === 'DIV') {\r\n // Look for li inside the div\r\n listItem = child.querySelector('li');\r\n }\r\n\r\n if (listItem) {\r\n const isBullet = listItem.classList.contains('bullet-list');\r\n const isOrdered = listItem.classList.contains('ordered-list');\r\n\r\n if (!isBullet && !isOrdered) {\r\n currentList = null;\r\n listType = null;\r\n continue;\r\n }\r\n\r\n const newType = isBullet ? 'ul' : 'ol';\r\n\r\n // Start new list or continue current\r\n if (!currentList || listType !== newType) {\r\n currentList = document.createElement(newType);\r\n container.insertBefore(currentList, child);\r\n listType = newType;\r\n }\r\n\r\n // Extract and preserve indentation from the div before moving the list item\r\n const indentationNodes = [];\r\n for (const node of child.childNodes) {\r\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\r\n // This is a text node containing only non-breaking spaces (indentation)\r\n indentationNodes.push(node.cloneNode(true));\r\n } else if (node === listItem) {\r\n break; // Stop when we reach the list item\r\n }\r\n }\r\n\r\n // Add indentation to the list item\r\n indentationNodes.forEach(node => {\r\n listItem.insertBefore(node, listItem.firstChild);\r\n });\r\n\r\n // Move the list item to the current list\r\n currentList.appendChild(listItem);\r\n\r\n // Remove the now-empty div wrapper\r\n child.remove();\r\n } else {\r\n // Non-list element ends current list\r\n currentList = null;\r\n listType = null;\r\n }\r\n }\r\n\r\n return container.innerHTML;\r\n }\r\n\r\n /**\r\n * Manual post-processing for Node.js environments (without DOM)\r\n * @param {string} html - HTML to post-process\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Post-processed HTML\r\n */\r\n static postProcessHTMLManual(html, instanceHighlighter) {\r\n let processed = html;\r\n\r\n // Process unordered lists\r\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\r\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\r\n if (divs.length > 0) {\r\n const items = divs.map(div => {\r\n // Extract indentation and list item\r\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\r\n\r\n if (indentMatch && listItemMatch) {\r\n const indentation = indentMatch[1];\r\n const listItem = listItemMatch[0];\r\n // Insert indentation at the start of the list item content\r\n return listItem.replace(/
  • /, `
  • ${indentation}`);\r\n }\r\n return listItemMatch ? listItemMatch[0] : '';\r\n }).filter(Boolean);\r\n\r\n return '
      ' + items.join('') + '
    ';\r\n }\r\n return match;\r\n });\r\n\r\n // Process ordered lists\r\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\r\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\r\n if (divs.length > 0) {\r\n const items = divs.map(div => {\r\n // Extract indentation and list item\r\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\r\n\r\n if (indentMatch && listItemMatch) {\r\n const indentation = indentMatch[1];\r\n const listItem = listItemMatch[0];\r\n // Insert indentation at the start of the list item content\r\n return listItem.replace(/
  • /, `
  • ${indentation}`);\r\n }\r\n return listItemMatch ? listItemMatch[0] : '';\r\n }).filter(Boolean);\r\n\r\n return '
      ' + items.join('') + '
    ';\r\n }\r\n return match;\r\n });\r\n\r\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\r\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\r\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\r\n // Extract the content between fences\r\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\r\n const codeContent = lines.map(line => {\r\n // Extract text from each div - content is already escaped\r\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\r\n .replace(/ /g, ' ');\r\n return text;\r\n }).join('\\n');\r\n\r\n // Extract language from the opening fence\r\n const lang = openFence.slice(3).trim();\r\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\r\n\r\n // Apply code highlighting if available\r\n let highlightedContent = codeContent;\r\n // Use instance highlighter if provided, otherwise fall back to global highlighter\r\n const highlighter = instanceHighlighter || this.codeHighlighter;\r\n if (highlighter) {\r\n try {\r\n // CRITICAL: Decode HTML entities before passing to highlighter\r\n // In the DOM path, textContent automatically decodes entities.\r\n // In the manual path, we need to decode explicitly to avoid double-escaping.\r\n const decodedCode = codeContent\r\n .replace(/"/g, '\"')\r\n .replace(/'/g, \"'\")\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\r\n\r\n const result = highlighter(decodedCode, lang);\r\n\r\n // Check if result is a Promise (async highlighter)\r\n // Note: In Node.js context, we can't easily defer rendering, so we warn\r\n if (result && typeof result.then === 'function') {\r\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\r\n // Fall back to escaped content\r\n } else {\r\n // Synchronous highlighter - verify returned non-empty string\r\n if (result && typeof result === 'string' && result.trim()) {\r\n highlightedContent = result;\r\n }\r\n // else: keep the escaped codeContent as fallback\r\n }\r\n } catch (error) {\r\n console.warn('Code highlighting failed:', error);\r\n // Fall back to original content\r\n }\r\n }\r\n\r\n // Keep fence markers visible as separate divs, with pre/code block between them\r\n let result = `
    ${openFence}
    `;\r\n // Use highlighted content if available, otherwise use escaped content\r\n result += `
    ${highlightedContent}
    `;\r\n result += `
    ${closeFence}
    `;\r\n\r\n return result;\r\n });\r\n\r\n return processed;\r\n }\r\n\r\n /**\r\n * List pattern definitions\r\n */\r\n static LIST_PATTERNS = {\r\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\r\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\r\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\r\n };\r\n\r\n /**\r\n * Get list context at cursor position\r\n * @param {string} text - Full text content\r\n * @param {number} cursorPosition - Current cursor position\r\n * @returns {Object} List context information\r\n */\r\n static getListContext(text, cursorPosition) {\r\n // Find the line containing the cursor\r\n const lines = text.split('\\n');\r\n let currentPos = 0;\r\n let lineIndex = 0;\r\n let lineStart = 0;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const lineLength = lines[i].length;\r\n if (currentPos + lineLength >= cursorPosition) {\r\n lineIndex = i;\r\n lineStart = currentPos;\r\n break;\r\n }\r\n currentPos += lineLength + 1; // +1 for newline\r\n }\r\n\r\n const currentLine = lines[lineIndex];\r\n const lineEnd = lineStart + currentLine.length;\r\n\r\n // Check for checkbox first (most specific)\r\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\r\n if (checkboxMatch) {\r\n return {\r\n inList: true,\r\n listType: 'checkbox',\r\n indent: checkboxMatch[1],\r\n marker: '-',\r\n checked: checkboxMatch[2] === 'x',\r\n content: checkboxMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\r\n };\r\n }\r\n\r\n // Check for bullet list\r\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\r\n if (bulletMatch) {\r\n return {\r\n inList: true,\r\n listType: 'bullet',\r\n indent: bulletMatch[1],\r\n marker: bulletMatch[2],\r\n content: bulletMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\r\n };\r\n }\r\n\r\n // Check for numbered list\r\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\r\n if (numberedMatch) {\r\n return {\r\n inList: true,\r\n listType: 'numbered',\r\n indent: numberedMatch[1],\r\n marker: parseInt(numberedMatch[2]),\r\n content: numberedMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\r\n };\r\n }\r\n\r\n // Not in a list\r\n return {\r\n inList: false,\r\n listType: null,\r\n indent: '',\r\n marker: null,\r\n content: currentLine,\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart\r\n };\r\n }\r\n\r\n /**\r\n * Create a new list item based on context\r\n * @param {Object} context - List context from getListContext\r\n * @returns {string} New list item text\r\n */\r\n static createNewListItem(context) {\r\n switch (context.listType) {\r\n case 'bullet':\r\n return `${context.indent}${context.marker} `;\r\n case 'numbered':\r\n return `${context.indent}${context.marker + 1}. `;\r\n case 'checkbox':\r\n return `${context.indent}- [ ] `;\r\n default:\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Renumber all numbered lists in text\r\n * @param {string} text - Text containing numbered lists\r\n * @returns {string} Text with renumbered lists\r\n */\r\n static renumberLists(text) {\r\n const lines = text.split('\\n');\r\n const numbersByIndent = new Map();\r\n let inList = false;\r\n\r\n const result = lines.map(line => {\r\n const match = line.match(this.LIST_PATTERNS.numbered);\r\n\r\n if (match) {\r\n const indent = match[1];\r\n const indentLevel = indent.length;\r\n const content = match[3];\r\n\r\n // If we weren't in a list or indent changed, reset lower levels\r\n if (!inList) {\r\n numbersByIndent.clear();\r\n }\r\n\r\n // Get the next number for this indent level\r\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\r\n numbersByIndent.set(indentLevel, currentNumber);\r\n\r\n // Clear deeper indent levels\r\n for (const [level] of numbersByIndent) {\r\n if (level > indentLevel) {\r\n numbersByIndent.delete(level);\r\n }\r\n }\r\n\r\n inList = true;\r\n return `${indent}${currentNumber}. ${content}`;\r\n } else {\r\n // Not a numbered list item\r\n if (line.trim() === '' || !line.match(/^\\s/)) {\r\n // Empty line or non-indented line breaks the list\r\n inList = false;\r\n numbersByIndent.clear();\r\n }\r\n return line;\r\n }\r\n });\r\n\r\n return result.join('\\n');\r\n }\r\n}\r\n", "/**\r\n * Keyboard shortcuts handler for OverType editor\r\n * Delegates to editor.performAction for consistent behavior\r\n */\r\n\r\n/**\r\n * ShortcutsManager - Handles keyboard shortcuts for the editor\r\n */\r\nexport class ShortcutsManager {\r\n constructor(editor) {\r\n this.editor = editor;\r\n }\r\n\r\n /**\r\n * Handle keydown events - called by OverType\r\n * @param {KeyboardEvent} event - The keyboard event\r\n * @returns {boolean} Whether the event was handled\r\n */\r\n handleKeydown(event) {\r\n const isMac = navigator.platform.toLowerCase().includes('mac');\r\n const modKey = isMac ? event.metaKey : event.ctrlKey;\r\n\r\n if (!modKey) return false;\r\n\r\n let actionId = null;\r\n\r\n switch (event.key.toLowerCase()) {\r\n case 'b':\r\n if (!event.shiftKey) actionId = 'toggleBold';\r\n break;\r\n case 'i':\r\n if (!event.shiftKey) actionId = 'toggleItalic';\r\n break;\r\n case 'k':\r\n if (!event.shiftKey) actionId = 'insertLink';\r\n break;\r\n case '7':\r\n if (event.shiftKey) actionId = 'toggleNumberedList';\r\n break;\r\n case '8':\r\n if (event.shiftKey) actionId = 'toggleBulletList';\r\n break;\r\n }\r\n\r\n if (actionId) {\r\n event.preventDefault();\r\n this.editor.performAction(actionId, event);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy() {\r\n // Nothing to clean up since we don't add our own listener\r\n }\r\n}\r\n", "/**\r\n * Built-in themes for OverType editor\r\n * Each theme provides a complete color palette for the editor\r\n */\r\n\r\n/**\r\n * Solar theme - Light, warm and bright\r\n */\r\nexport const solar = {\r\n name: 'solar',\r\n colors: {\r\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\r\n bgSecondary: '#ffffff', // White - editor background\r\n text: '#0d3b66', // Yale Blue - main text\r\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\r\n textSecondary: '#5a7a9b', // Muted blue - secondary text\r\n h1: '#f95738', // Tomato - h1 headers\r\n h2: '#ee964b', // Sandy Brown - h2 headers\r\n h3: '#3d8a51', // Forest green - h3 headers\r\n strong: '#ee964b', // Sandy Brown - bold text\r\n em: '#f95738', // Tomato - italic text\r\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\r\n link: '#0d3b66', // Yale Blue - links\r\n code: '#0d3b66', // Yale Blue - inline code\r\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\r\n blockquote: '#5a7a9b', // Muted blue - blockquotes\r\n hr: '#5a7a9b', // Muted blue - horizontal rules\r\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\r\n syntax: '#999999', // Gray - syntax highlighting fallback\r\n cursor: '#f95738', // Tomato - cursor\r\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\r\n listMarker: '#ee964b', // Sandy Brown - list markers\r\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\r\n border: '#e0e0e0', // Light gray - borders\r\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\r\n primary: '#0d3b66', // Yale Blue - primary accent\r\n // Toolbar colors\r\n toolbarBg: '#ffffff', // White - toolbar background\r\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\r\n toolbarHover: '#f5f5f5', // Light gray - hover background\r\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\r\n }\r\n};\r\n\r\n/**\r\n * Cave theme - Dark ocean depths\r\n */\r\nexport const cave = {\r\n name: 'cave',\r\n colors: {\r\n bgPrimary: '#141E26', // Deep ocean - main background\r\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\r\n text: '#c5dde8', // Light blue-gray - main text\r\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\r\n textSecondary: '#9fcfec', // Brighter blue - secondary text\r\n h1: '#d4a5ff', // Rich lavender - h1 headers\r\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\r\n h3: '#9fcfec', // Brighter blue - h3 headers\r\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\r\n em: '#9fcfec', // Brighter blue - italic text\r\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\r\n link: '#9fcfec', // Brighter blue - links\r\n code: '#c5dde8', // Light blue-gray - inline code\r\n codeBg: '#1a232b', // Very dark blue - code background\r\n blockquote: '#9fcfec', // Brighter blue - same as italic\r\n hr: '#c5dde8', // Light blue-gray - horizontal rules\r\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\r\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\r\n cursor: '#f26419', // Orange Pantone - cursor\r\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\r\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\r\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\r\n border: '#2a3f52', // Dark blue-gray - borders\r\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\r\n primary: '#9fcfec', // Brighter blue - primary accent\r\n // Toolbar colors for dark theme\r\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\r\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\r\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\r\n toolbarActive: '#2a3f52', // Even lighter - active button background\r\n }\r\n};\r\n\r\n/**\r\n * Auto theme - Automatically switches between solar and cave based on system preference\r\n * This is a special marker theme that triggers automatic theme switching\r\n */\r\nexport const auto = {\r\n name: 'auto',\r\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\r\n colors: solar.colors // Default to solar colors for initial render\r\n};\r\n\r\n/**\r\n * Default themes registry\r\n */\r\nexport const themes = {\r\n solar,\r\n cave,\r\n auto,\r\n // Aliases for backward compatibility\r\n light: solar,\r\n dark: cave\r\n};\r\n\r\n/**\r\n * Get theme by name or return custom theme object\r\n * @param {string|Object} theme - Theme name or custom theme object\r\n * @returns {Object} Theme configuration\r\n */\r\nexport function getTheme(theme) {\r\n if (typeof theme === 'string') {\r\n const themeObj = themes[theme] || themes.solar;\r\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\r\n return { ...themeObj, name: theme };\r\n }\r\n return theme;\r\n}\r\n\r\n/**\r\n * Resolve auto theme to actual theme based on system color scheme preference\r\n * @param {string} themeName - Theme name to resolve\r\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\r\n */\r\nexport function resolveAutoTheme(themeName) {\r\n if (themeName !== 'auto') {\r\n return themeName;\r\n }\r\n\r\n // Check for system dark mode preference\r\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n return isDarkMode ? 'cave' : 'solar';\r\n}\r\n\r\n/**\r\n * Get the current system color scheme preference\r\n * @returns {string} 'dark' or 'light'\r\n */\r\nexport function getSystemColorScheme() {\r\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n return isDarkMode ? 'dark' : 'light';\r\n}\r\n\r\n/**\r\n * Apply theme colors to CSS variables\r\n * @param {Object} colors - Theme colors object\r\n * @returns {string} CSS custom properties string\r\n */\r\nexport function themeToCSSVars(colors) {\r\n const vars = [];\r\n for (const [key, value] of Object.entries(colors)) {\r\n // Convert camelCase to kebab-case\r\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n vars.push(`--${varName}: ${value};`);\r\n }\r\n return vars.join('\\n');\r\n}\r\n\r\n/**\r\n * Merge custom colors with base theme\r\n * @param {Object} baseTheme - Base theme object\r\n * @param {Object} customColors - Custom color overrides\r\n * @returns {Object} Merged theme object\r\n */\r\nexport function mergeTheme(baseTheme, customColors = {}) {\r\n return {\r\n ...baseTheme,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customColors\r\n }\r\n };\r\n}", "/**\r\n * CSS styles for OverType editor\r\n * Embedded in JavaScript to ensure single-file distribution\r\n */\r\n\r\nimport { themeToCSSVars } from './themes.js';\r\n\r\n/**\r\n * Generate the complete CSS for the editor\r\n * @param {Object} options - Configuration options\r\n * @returns {string} Complete CSS string\r\n */\r\nexport function generateStyles(options = {}) {\r\n const {\r\n fontSize = '14px',\r\n lineHeight = 1.6,\r\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\r\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\r\n padding = '20px',\r\n theme = null,\r\n mobile = {}\r\n } = options;\r\n\r\n // Generate mobile overrides\r\n const mobileStyles = Object.keys(mobile).length > 0 ? `\r\n @media (max-width: 640px) {\r\n .overtype-wrapper .overtype-input,\r\n .overtype-wrapper .overtype-preview {\r\n ${Object.entries(mobile)\r\n .map(([prop, val]) => {\r\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n return `${cssProp}: ${val} !important;`;\r\n })\r\n .join('\\n ')}\r\n }\r\n }\r\n ` : '';\r\n\r\n // Generate theme variables if provided\r\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\r\n\r\n return `\r\n /* OverType Editor Styles */\r\n \r\n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\r\n .overtype-container * {\r\n /* Box model - these commonly leak */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: 0 !important;\r\n \r\n /* Layout - these can break our layout */\r\n /* Don't reset position - it breaks dropdowns */\r\n float: none !important;\r\n clear: none !important;\r\n \r\n /* Typography - only reset decorative aspects */\r\n text-decoration: none !important;\r\n text-transform: none !important;\r\n letter-spacing: normal !important;\r\n \r\n /* Visual effects that can interfere */\r\n box-shadow: none !important;\r\n text-shadow: none !important;\r\n \r\n /* Ensure box-sizing is consistent */\r\n box-sizing: border-box !important;\r\n \r\n /* Keep inheritance for these */\r\n /* font-family, color, line-height, font-size - inherit */\r\n }\r\n \r\n /* Container base styles after reset */\r\n .overtype-container {\r\n display: flex !important;\r\n flex-direction: column !important;\r\n width: 100% !important;\r\n height: 100% !important;\r\n position: relative !important; /* Override reset - needed for absolute children */\r\n overflow: visible !important; /* Allow dropdown to overflow container */\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\r\n text-align: left !important;\r\n ${themeVars ? `\r\n /* Theme Variables */\r\n ${themeVars}` : ''}\r\n }\r\n \r\n /* Force left alignment for all elements in the editor */\r\n .overtype-container .overtype-wrapper * {\r\n text-align: left !important;\r\n }\r\n \r\n /* Auto-resize mode styles */\r\n .overtype-container.overtype-auto-resize {\r\n height: auto !important;\r\n }\r\n\r\n .overtype-container.overtype-auto-resize .overtype-wrapper {\r\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\r\n height: auto !important;\r\n min-height: 60px !important;\r\n overflow: visible !important;\r\n }\r\n \r\n .overtype-wrapper {\r\n position: relative !important; /* Override reset - needed for absolute children */\r\n width: 100% !important;\r\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\r\n min-height: 60px !important; /* Minimum usable height */\r\n overflow: hidden !important;\r\n background: var(--bg-secondary, #ffffff) !important;\r\n z-index: 1; /* Below toolbar and dropdown */\r\n }\r\n\r\n /* Critical alignment styles - must be identical for both layers */\r\n .overtype-wrapper .overtype-input,\r\n .overtype-wrapper .overtype-preview {\r\n /* Positioning - must be identical */\r\n position: absolute !important; /* Override reset - required for overlay */\r\n top: 0 !important;\r\n left: 0 !important;\r\n width: 100% !important;\r\n height: 100% !important;\r\n \r\n /* Font properties - any difference breaks alignment */\r\n font-family: ${fontFamily} !important;\r\n font-variant-ligatures: none !important; /* keep metrics stable for code */\r\n font-size: var(--instance-font-size, ${fontSize}) !important;\r\n line-height: var(--instance-line-height, ${lineHeight}) !important;\r\n font-weight: normal !important;\r\n font-style: normal !important;\r\n font-variant: normal !important;\r\n font-stretch: normal !important;\r\n font-kerning: none !important;\r\n font-feature-settings: normal !important;\r\n \r\n /* Box model - must match exactly */\r\n padding: var(--instance-padding, ${padding}) !important;\r\n margin: 0 !important;\r\n border: none !important;\r\n outline: none !important;\r\n box-sizing: border-box !important;\r\n \r\n /* Text layout - critical for character positioning */\r\n white-space: pre-wrap !important;\r\n word-wrap: break-word !important;\r\n word-break: normal !important;\r\n overflow-wrap: break-word !important;\r\n tab-size: 2 !important;\r\n -moz-tab-size: 2 !important;\r\n text-align: left !important;\r\n text-indent: 0 !important;\r\n letter-spacing: normal !important;\r\n word-spacing: normal !important;\r\n \r\n /* Text rendering */\r\n text-transform: none !important;\r\n text-rendering: auto !important;\r\n -webkit-font-smoothing: auto !important;\r\n -webkit-text-size-adjust: 100% !important;\r\n \r\n /* Direction and writing */\r\n direction: ltr !important;\r\n writing-mode: horizontal-tb !important;\r\n unicode-bidi: normal !important;\r\n text-orientation: mixed !important;\r\n \r\n /* Visual effects that could shift perception */\r\n text-shadow: none !important;\r\n filter: none !important;\r\n transform: none !important;\r\n zoom: 1 !important;\r\n \r\n /* Vertical alignment */\r\n vertical-align: baseline !important;\r\n \r\n /* Size constraints */\r\n min-width: 0 !important;\r\n min-height: 0 !important;\r\n max-width: none !important;\r\n max-height: none !important;\r\n \r\n /* Overflow */\r\n overflow-y: auto !important;\r\n overflow-x: auto !important;\r\n /* overscroll-behavior removed to allow scroll-through to parent */\r\n scrollbar-width: auto !important;\r\n scrollbar-gutter: auto !important;\r\n \r\n /* Animation/transition - disabled to prevent movement */\r\n animation: none !important;\r\n transition: none !important;\r\n }\r\n\r\n /* Input layer styles */\r\n .overtype-wrapper .overtype-input {\r\n /* Layer positioning */\r\n z-index: 1 !important;\r\n \r\n /* Text visibility */\r\n color: transparent !important;\r\n caret-color: var(--cursor, #f95738) !important;\r\n background-color: transparent !important;\r\n \r\n /* Textarea-specific */\r\n resize: none !important;\r\n appearance: none !important;\r\n -webkit-appearance: none !important;\r\n -moz-appearance: none !important;\r\n \r\n /* Prevent mobile zoom on focus */\r\n touch-action: manipulation !important;\r\n \r\n /* Disable autofill and spellcheck */\r\n autocomplete: off !important;\r\n autocorrect: off !important;\r\n autocapitalize: off !important;\r\n spellcheck: false !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-input::selection {\r\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\r\n }\r\n\r\n /* Preview layer styles */\r\n .overtype-wrapper .overtype-preview {\r\n /* Layer positioning */\r\n z-index: 0 !important;\r\n pointer-events: none !important;\r\n color: var(--text, #0d3b66) !important;\r\n background-color: transparent !important;\r\n \r\n /* Prevent text selection */\r\n user-select: none !important;\r\n -webkit-user-select: none !important;\r\n -moz-user-select: none !important;\r\n -ms-user-select: none !important;\r\n }\r\n\r\n /* Defensive styles for preview child divs */\r\n .overtype-wrapper .overtype-preview div {\r\n /* Reset any inherited styles */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: none !important;\r\n text-align: left !important;\r\n text-indent: 0 !important;\r\n display: block !important;\r\n position: static !important;\r\n transform: none !important;\r\n min-height: 0 !important;\r\n max-height: none !important;\r\n line-height: inherit !important;\r\n font-size: inherit !important;\r\n font-family: inherit !important;\r\n }\r\n\r\n /* Markdown element styling - NO SIZE CHANGES */\r\n .overtype-wrapper .overtype-preview .header {\r\n font-weight: bold !important;\r\n }\r\n\r\n /* Header colors */\r\n .overtype-wrapper .overtype-preview .h1 { \r\n color: var(--h1, #f95738) !important; \r\n }\r\n .overtype-wrapper .overtype-preview .h2 { \r\n color: var(--h2, #ee964b) !important; \r\n }\r\n .overtype-wrapper .overtype-preview .h3 { \r\n color: var(--h3, #3d8a51) !important; \r\n }\r\n\r\n /* Semantic headers - flatten in edit mode */\r\n .overtype-wrapper .overtype-preview h1,\r\n .overtype-wrapper .overtype-preview h2,\r\n .overtype-wrapper .overtype-preview h3 {\r\n font-size: inherit !important;\r\n font-weight: bold !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n display: inline !important;\r\n line-height: inherit !important;\r\n }\r\n\r\n /* Header colors for semantic headers */\r\n .overtype-wrapper .overtype-preview h1 { \r\n color: var(--h1, #f95738) !important; \r\n }\r\n .overtype-wrapper .overtype-preview h2 { \r\n color: var(--h2, #ee964b) !important; \r\n }\r\n .overtype-wrapper .overtype-preview h3 { \r\n color: var(--h3, #3d8a51) !important; \r\n }\r\n\r\n /* Lists - remove styling in edit mode */\r\n .overtype-wrapper .overtype-preview ul,\r\n .overtype-wrapper .overtype-preview ol {\r\n list-style: none !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n display: block !important; /* Lists need to be block for line breaks */\r\n }\r\n\r\n .overtype-wrapper .overtype-preview li {\r\n display: block !important; /* Each item on its own line */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n /* Don't set list-style here - let ul/ol control it */\r\n }\r\n\r\n /* Bold text */\r\n .overtype-wrapper .overtype-preview strong {\r\n color: var(--strong, #ee964b) !important;\r\n font-weight: bold !important;\r\n }\r\n\r\n /* Italic text */\r\n .overtype-wrapper .overtype-preview em {\r\n color: var(--em, #f95738) !important;\r\n text-decoration-color: var(--em, #f95738) !important;\r\n text-decoration-thickness: 1px !important;\r\n font-style: italic !important;\r\n }\r\n\r\n /* Strikethrough text */\r\n .overtype-wrapper .overtype-preview del {\r\n color: var(--del, #ee964b) !important;\r\n text-decoration: line-through !important;\r\n text-decoration-color: var(--del, #ee964b) !important;\r\n text-decoration-thickness: 1px !important;\r\n }\r\n\r\n /* Inline code */\r\n .overtype-wrapper .overtype-preview code {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n color: var(--code, #0d3b66) !important;\r\n padding: 0 !important;\r\n border-radius: 2px !important;\r\n font-family: inherit !important;\r\n font-size: inherit !important;\r\n line-height: inherit !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Code blocks - consolidated pre blocks */\r\n .overtype-wrapper .overtype-preview pre {\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n border-radius: 4px !important;\r\n overflow-x: auto !important;\r\n }\r\n \r\n /* Code block styling in normal mode - yellow background */\r\n .overtype-wrapper .overtype-preview pre.code-block {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\r\n }\r\n\r\n /* Code inside pre blocks - remove background */\r\n .overtype-wrapper .overtype-preview pre code {\r\n background: transparent !important;\r\n color: var(--code, #0d3b66) !important;\r\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\r\n }\r\n\r\n /* Blockquotes */\r\n .overtype-wrapper .overtype-preview .blockquote {\r\n color: var(--blockquote, #5a7a9b) !important;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n border: none !important;\r\n }\r\n\r\n /* Links */\r\n .overtype-wrapper .overtype-preview a {\r\n color: var(--link, #0d3b66) !important;\r\n text-decoration: underline !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-preview a:hover {\r\n text-decoration: underline !important;\r\n color: var(--link, #0d3b66) !important;\r\n }\r\n\r\n /* Lists - no list styling */\r\n .overtype-wrapper .overtype-preview ul,\r\n .overtype-wrapper .overtype-preview ol {\r\n list-style: none !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n\r\n /* Horizontal rules */\r\n .overtype-wrapper .overtype-preview hr {\r\n border: none !important;\r\n color: var(--hr, #5a7a9b) !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-preview .hr-marker {\r\n color: var(--hr, #5a7a9b) !important;\r\n opacity: 0.6 !important;\r\n }\r\n\r\n /* Code fence markers - with background when not in code block */\r\n .overtype-wrapper .overtype-preview .code-fence {\r\n color: var(--code, #0d3b66) !important;\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n }\r\n \r\n /* Code block lines - background for entire code block */\r\n .overtype-wrapper .overtype-preview .code-block-line {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n }\r\n \r\n /* Remove background from code fence when inside code block line */\r\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\r\n background: transparent !important;\r\n }\r\n\r\n /* Raw markdown line */\r\n .overtype-wrapper .overtype-preview .raw-line {\r\n color: var(--raw-line, #5a7a9b) !important;\r\n font-style: normal !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Syntax markers */\r\n .overtype-wrapper .overtype-preview .syntax-marker {\r\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\r\n opacity: 0.7 !important;\r\n }\r\n\r\n /* List markers */\r\n .overtype-wrapper .overtype-preview .list-marker {\r\n color: var(--list-marker, #ee964b) !important;\r\n }\r\n\r\n /* Stats bar */\r\n \r\n /* Stats bar - positioned by flexbox */\r\n .overtype-stats {\r\n height: 40px !important;\r\n padding: 0 20px !important;\r\n background: #f8f9fa !important;\r\n border-top: 1px solid #e0e0e0 !important;\r\n display: flex !important;\r\n justify-content: space-between !important;\r\n align-items: center !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\r\n font-size: 0.85rem !important;\r\n color: #666 !important;\r\n flex-shrink: 0 !important; /* Don't shrink */\r\n z-index: 10001 !important; /* Above link tooltip */\r\n position: relative !important; /* Enable z-index */\r\n }\r\n \r\n /* Dark theme stats bar */\r\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\r\n background: var(--bg-secondary, #1D2D3E) !important;\r\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\r\n color: var(--text, #c5dde8) !important;\r\n }\r\n \r\n .overtype-stats .overtype-stat {\r\n display: flex !important;\r\n align-items: center !important;\r\n gap: 5px !important;\r\n white-space: nowrap !important;\r\n }\r\n \r\n .overtype-stats .live-dot {\r\n width: 8px !important;\r\n height: 8px !important;\r\n background: #4caf50 !important;\r\n border-radius: 50% !important;\r\n animation: overtype-pulse 2s infinite !important;\r\n }\r\n \r\n @keyframes overtype-pulse {\r\n 0%, 100% { opacity: 1; transform: scale(1); }\r\n 50% { opacity: 0.6; transform: scale(1.2); }\r\n }\r\n \r\n\r\n /* Toolbar Styles */\r\n .overtype-toolbar {\r\n display: flex !important;\r\n align-items: center !important;\r\n gap: 4px !important;\r\n padding: 8px !important; /* Override reset */\r\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\r\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\r\n overflow-x: auto !important; /* Allow horizontal scrolling */\r\n overflow-y: hidden !important; /* Hide vertical overflow */\r\n -webkit-overflow-scrolling: touch !important;\r\n flex-shrink: 0 !important;\r\n height: auto !important;\r\n position: relative !important; /* Override reset */\r\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\r\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\r\n }\r\n \r\n /* Thin scrollbar styling */\r\n .overtype-toolbar::-webkit-scrollbar {\r\n height: 4px;\r\n }\r\n \r\n .overtype-toolbar::-webkit-scrollbar-track {\r\n background: transparent;\r\n }\r\n \r\n .overtype-toolbar::-webkit-scrollbar-thumb {\r\n background: rgba(0, 0, 0, 0.2);\r\n border-radius: 2px;\r\n }\r\n\r\n .overtype-toolbar-button {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 6px;\r\n background: transparent;\r\n color: var(--toolbar-icon, var(--text-secondary, #666));\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n\r\n .overtype-toolbar-button svg {\r\n width: 20px;\r\n height: 20px;\r\n fill: currentColor;\r\n }\r\n\r\n .overtype-toolbar-button:hover {\r\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\r\n color: var(--toolbar-icon, var(--text-primary, #333));\r\n }\r\n\r\n .overtype-toolbar-button:active {\r\n transform: scale(0.95);\r\n }\r\n\r\n .overtype-toolbar-button.active {\r\n background: var(--toolbar-active, var(--primary, #007bff));\r\n color: var(--toolbar-icon, var(--text-primary, #333));\r\n }\r\n\r\n .overtype-toolbar-button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .overtype-toolbar-separator {\r\n width: 1px;\r\n height: 24px;\r\n background: var(--border, #e0e0e0);\r\n margin: 0 4px;\r\n flex-shrink: 0;\r\n }\r\n\r\n /* Adjust wrapper when toolbar is present */\r\n /* Mobile toolbar adjustments */\r\n @media (max-width: 640px) {\r\n .overtype-toolbar {\r\n padding: 6px;\r\n gap: 2px;\r\n }\r\n\r\n .overtype-toolbar-button {\r\n width: 36px;\r\n height: 36px;\r\n }\r\n\r\n .overtype-toolbar-separator {\r\n margin: 0 2px;\r\n }\r\n }\r\n \r\n /* Plain mode - hide preview and show textarea text */\r\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\r\n display: none !important;\r\n }\r\n \r\n .overtype-container[data-mode=\"plain\"] .overtype-input {\r\n color: var(--text, #0d3b66) !important;\r\n /* Use system font stack for better plain text readability */\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \r\n \"Helvetica Neue\", Arial, sans-serif !important;\r\n }\r\n \r\n /* Ensure textarea remains transparent in overlay mode */\r\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\r\n color: transparent !important;\r\n }\r\n\r\n /* Dropdown menu styles */\r\n .overtype-toolbar-button {\r\n position: relative !important; /* Override reset - needed for dropdown */\r\n }\r\n\r\n .overtype-toolbar-button.dropdown-active {\r\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\r\n }\r\n\r\n .overtype-dropdown-menu {\r\n position: fixed !important; /* Fixed positioning relative to viewport */\r\n background: var(--bg-secondary, white) !important; /* Override reset */\r\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\r\n border-radius: 6px;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\r\n z-index: 10000; /* Very high z-index to ensure visibility */\r\n min-width: 150px;\r\n padding: 4px 0 !important; /* Override reset */\r\n /* Position will be set via JavaScript based on button position */\r\n }\r\n\r\n .overtype-dropdown-item {\r\n display: flex;\r\n align-items: center;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: none;\r\n background: none;\r\n text-align: left;\r\n cursor: pointer;\r\n font-size: 14px;\r\n color: var(--text, #333);\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\r\n }\r\n\r\n .overtype-dropdown-item:hover {\r\n background: var(--hover-bg, #f0f0f0);\r\n }\r\n\r\n .overtype-dropdown-item.active {\r\n font-weight: 600;\r\n }\r\n\r\n .overtype-dropdown-check {\r\n width: 16px;\r\n margin-right: 8px;\r\n color: var(--h1, #007bff);\r\n }\r\n\r\n .overtype-dropdown-icon {\r\n width: 20px;\r\n margin-right: 8px;\r\n text-align: center;\r\n }\r\n\r\n /* Preview mode styles */\r\n .overtype-container[data-mode=\"preview\"] .overtype-input {\r\n display: none !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\r\n pointer-events: auto !important;\r\n user-select: text !important;\r\n cursor: text !important;\r\n }\r\n\r\n /* Hide syntax markers in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\r\n display: none !important;\r\n }\r\n \r\n /* Hide URL part of links in preview mode - extra specificity */\r\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\r\n .overtype-container[data-mode=\"preview\"] .url-part {\r\n display: none !important;\r\n }\r\n \r\n /* Hide all syntax markers inside links too */\r\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\r\n display: none !important;\r\n }\r\n\r\n /* Headers - restore proper sizing in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\r\n font-weight: 600 !important;\r\n margin: 0 !important;\r\n display: block !important;\r\n color: inherit !important; /* Use parent text color */\r\n line-height: 1 !important; /* Tight line height for headings */\r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \r\n font-size: 2em !important; \r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \r\n font-size: 1.5em !important; \r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \r\n font-size: 1.17em !important; \r\n }\r\n\r\n /* Lists - restore list styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\r\n display: block !important;\r\n list-style: disc !important;\r\n padding-left: 2em !important;\r\n margin: 1em 0 !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\r\n display: block !important;\r\n list-style: decimal !important;\r\n padding-left: 2em !important;\r\n margin: 1em 0 !important;\r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\r\n display: list-item !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n /* Task list checkboxes - only in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\r\n list-style: none !important;\r\n position: relative !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\r\n margin-right: 0.5em !important;\r\n cursor: default !important;\r\n vertical-align: middle !important;\r\n }\r\n\r\n /* Task list in normal mode - keep syntax visible */\r\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\r\n list-style: none !important;\r\n }\r\n\r\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\r\n color: var(--syntax, #999999) !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Links - make clickable in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\r\n pointer-events: auto !important;\r\n cursor: pointer !important;\r\n color: var(--link, #0066cc) !important;\r\n text-decoration: underline !important;\r\n }\r\n\r\n /* Code blocks - proper pre/code styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\r\n background: #2d2d2d !important;\r\n color: #f8f8f2 !important;\r\n padding: 1.2em !important;\r\n border-radius: 3px !important;\r\n overflow-x: auto !important;\r\n margin: 0 !important;\r\n display: block !important;\r\n }\r\n \r\n /* Cave theme code block background in preview mode */\r\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\r\n background: #11171F !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\r\n background: transparent !important;\r\n color: inherit !important;\r\n padding: 0 !important;\r\n font-family: ${fontFamily} !important;\r\n font-size: 0.9em !important;\r\n line-height: 1.4 !important;\r\n }\r\n\r\n /* Hide old code block lines and fences in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\r\n display: none !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\r\n display: none !important;\r\n }\r\n\r\n /* Blockquotes - enhanced styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\r\n display: block !important;\r\n border-left: 4px solid var(--blockquote, #ddd) !important;\r\n padding-left: 1em !important;\r\n margin: 1em 0 !important;\r\n font-style: italic !important;\r\n }\r\n\r\n /* Typography improvements in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\r\n font-family: Georgia, 'Times New Roman', serif !important;\r\n font-size: 16px !important;\r\n line-height: 1.8 !important;\r\n color: var(--text, #333) !important; /* Consistent text color */\r\n }\r\n\r\n /* Inline code in preview mode - keep monospace */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\r\n font-family: ${fontFamily} !important;\r\n font-size: 0.9em !important;\r\n background: rgba(135, 131, 120, 0.15) !important;\r\n padding: 0.2em 0.4em !important;\r\n border-radius: 3px !important;\r\n }\r\n\r\n /* Strong and em elements in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\r\n font-weight: 700 !important;\r\n color: inherit !important; /* Use parent text color */\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\r\n font-style: italic !important;\r\n color: inherit !important; /* Use parent text color */\r\n }\r\n\r\n /* HR in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\r\n display: block !important;\r\n border-top: 2px solid var(--hr, #ddd) !important;\r\n text-indent: -9999px !important;\r\n height: 2px !important;\r\n }\r\n\r\n /* Link Tooltip - Base styles (all browsers) */\r\n .overtype-link-tooltip {\r\n /* Visual styles that work for both positioning methods */\r\n background: #333 !important;\r\n color: white !important;\r\n padding: 6px 10px !important;\r\n border-radius: 16px !important;\r\n font-size: 12px !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\r\n display: none !important;\r\n z-index: 10000 !important;\r\n cursor: pointer !important;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\r\n max-width: 300px !important;\r\n white-space: nowrap !important;\r\n overflow: hidden !important;\r\n text-overflow: ellipsis !important;\r\n\r\n /* Base positioning for Floating UI fallback */\r\n position: absolute;\r\n }\r\n\r\n .overtype-link-tooltip.visible {\r\n display: flex !important;\r\n }\r\n\r\n /* CSS Anchor Positioning (modern browsers only) */\r\n @supports (position-anchor: --x) and (position-area: center) {\r\n .overtype-link-tooltip {\r\n /* Only anchor positioning specific properties */\r\n position-anchor: var(--target-anchor, --link-0);\r\n position-area: block-end center;\r\n margin-top: 8px !important;\r\n position-try: most-width block-end inline-end, flip-inline, block-start center;\r\n position-visibility: anchors-visible;\r\n }\r\n }\r\n\r\n ${mobileStyles}\r\n `;\r\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\r\n * Toolbar component for OverType editor\r\n * Provides markdown formatting buttons with support for custom buttons\r\n */\r\n\r\nimport * as markdownActions from 'markdown-actions';\r\n\r\nexport class Toolbar {\r\n constructor(editor, options = {}) {\r\n this.editor = editor;\r\n this.container = null;\r\n this.buttons = {};\r\n\r\n // Get toolbar buttons array\r\n this.toolbarButtons = options.toolbarButtons || [];\r\n }\r\n\r\n /**\r\n * Create and render toolbar\r\n */\r\n create() {\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-toolbar';\r\n this.container.setAttribute('role', 'toolbar');\r\n this.container.setAttribute('aria-label', 'Formatting toolbar');\r\n\r\n // Create buttons from toolbarButtons array\r\n this.toolbarButtons.forEach(buttonConfig => {\r\n if (buttonConfig.name === 'separator') {\r\n const separator = this.createSeparator();\r\n this.container.appendChild(separator);\r\n } else {\r\n const button = this.createButton(buttonConfig);\r\n this.buttons[buttonConfig.name] = button;\r\n this.container.appendChild(button);\r\n }\r\n });\r\n\r\n // Insert toolbar before the wrapper (as sibling, not child)\r\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\r\n }\r\n\r\n /**\r\n * Create a toolbar separator\r\n */\r\n createSeparator() {\r\n const separator = document.createElement('div');\r\n separator.className = 'overtype-toolbar-separator';\r\n separator.setAttribute('role', 'separator');\r\n return separator;\r\n }\r\n\r\n /**\r\n * Create a toolbar button\r\n */\r\n createButton(buttonConfig) {\r\n const button = document.createElement('button');\r\n button.className = 'overtype-toolbar-button';\r\n button.type = 'button';\r\n button.setAttribute('data-button', buttonConfig.name);\r\n button.title = buttonConfig.title || '';\r\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\r\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\r\n\r\n // Special handling for viewMode dropdown\r\n if (buttonConfig.name === 'viewMode') {\r\n button.classList.add('has-dropdown');\r\n button.dataset.dropdown = 'true';\r\n button.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n this.toggleViewModeDropdown(button);\r\n });\r\n return button;\r\n }\r\n\r\n // Standard button click handler - delegate to performAction\r\n button._clickHandler = (e) => {\r\n e.preventDefault();\r\n const actionId = buttonConfig.actionId || buttonConfig.name;\r\n this.editor.performAction(actionId, e);\r\n };\r\n\r\n button.addEventListener('click', button._clickHandler);\r\n return button;\r\n }\r\n\r\n /**\r\n * Handle button action programmatically\r\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\r\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\r\n * @returns {Promise} Whether the action was executed\r\n */\r\n async handleAction(actionIdOrConfig) {\r\n // Old style: buttonConfig object with .action function - execute directly\r\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\r\n this.editor.textarea.focus();\r\n try {\r\n await actionIdOrConfig.action({\r\n editor: this.editor,\r\n getValue: () => this.editor.getValue(),\r\n setValue: (value) => this.editor.setValue(value),\r\n event: null\r\n });\r\n return true;\r\n } catch (error) {\r\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\r\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\r\n detail: { buttonName: actionIdOrConfig.name, error }\r\n }));\r\n return false;\r\n }\r\n }\r\n\r\n // New style: string actionId - delegate to performAction\r\n if (typeof actionIdOrConfig === 'string') {\r\n return this.editor.performAction(actionIdOrConfig, null);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Sanitize SVG to prevent XSS\r\n */\r\n sanitizeSVG(svg) {\r\n if (typeof svg !== 'string') return '';\r\n\r\n // Remove script tags and on* event handlers\r\n const cleaned = svg\r\n .replace(/)<[^<]*)*<\\/script>/gi, '')\r\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\r\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\r\n\r\n return cleaned;\r\n }\r\n\r\n /**\r\n * Toggle view mode dropdown (internal implementation)\r\n * Not exposed to users - viewMode button behavior is fixed\r\n */\r\n toggleViewModeDropdown(button) {\r\n // Close any existing dropdown\r\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\r\n if (existingDropdown) {\r\n existingDropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n return;\r\n }\r\n\r\n button.classList.add('dropdown-active');\r\n\r\n const dropdown = this.createViewModeDropdown(button);\r\n\r\n // Position dropdown relative to button\r\n const rect = button.getBoundingClientRect();\r\n dropdown.style.position = 'absolute';\r\n dropdown.style.top = `${rect.bottom + 5}px`;\r\n dropdown.style.left = `${rect.left}px`;\r\n\r\n document.body.appendChild(dropdown);\r\n\r\n // Click outside to close\r\n this.handleDocumentClick = (e) => {\r\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\r\n dropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n }\r\n };\r\n\r\n setTimeout(() => {\r\n document.addEventListener('click', this.handleDocumentClick);\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Create view mode dropdown menu (internal implementation)\r\n */\r\n createViewModeDropdown(button) {\r\n const dropdown = document.createElement('div');\r\n dropdown.className = 'overtype-dropdown-menu';\r\n\r\n const items = [\r\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\r\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\r\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\r\n ];\r\n\r\n const currentMode = this.editor.container.dataset.mode || 'normal';\r\n\r\n items.forEach(item => {\r\n const menuItem = document.createElement('button');\r\n menuItem.className = 'overtype-dropdown-item';\r\n menuItem.type = 'button';\r\n menuItem.textContent = item.label;\r\n\r\n if (item.id === currentMode) {\r\n menuItem.classList.add('active');\r\n menuItem.setAttribute('aria-current', 'true');\r\n const checkmark = document.createElement('span');\r\n checkmark.className = 'overtype-dropdown-icon';\r\n checkmark.textContent = item.icon;\r\n menuItem.prepend(checkmark);\r\n }\r\n\r\n menuItem.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n\r\n // Handle view mode changes\r\n switch(item.id) {\r\n case 'plain':\r\n this.editor.showPlainTextarea();\r\n break;\r\n case 'preview':\r\n this.editor.showPreviewMode();\r\n break;\r\n case 'normal':\r\n default:\r\n this.editor.showNormalEditMode();\r\n break;\r\n }\r\n\r\n dropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n });\r\n\r\n dropdown.appendChild(menuItem);\r\n });\r\n\r\n return dropdown;\r\n }\r\n\r\n /**\r\n * Update active states of toolbar buttons\r\n */\r\n updateButtonStates() {\r\n try {\r\n const activeFormats = markdownActions.getActiveFormats?.(\r\n this.editor.textarea,\r\n this.editor.textarea.selectionStart\r\n ) || [];\r\n\r\n Object.entries(this.buttons).forEach(([name, button]) => {\r\n if (name === 'viewMode') return; // Skip dropdown button\r\n\r\n let isActive = false;\r\n\r\n switch(name) {\r\n case 'bold':\r\n isActive = activeFormats.includes('bold');\r\n break;\r\n case 'italic':\r\n isActive = activeFormats.includes('italic');\r\n break;\r\n case 'code':\r\n isActive = false; // Disabled: unreliable in code blocks\r\n break;\r\n case 'bulletList':\r\n isActive = activeFormats.includes('bullet-list');\r\n break;\r\n case 'orderedList':\r\n isActive = activeFormats.includes('numbered-list');\r\n break;\r\n case 'taskList':\r\n isActive = activeFormats.includes('task-list');\r\n break;\r\n case 'quote':\r\n isActive = activeFormats.includes('quote');\r\n break;\r\n case 'h1':\r\n isActive = activeFormats.includes('header');\r\n break;\r\n case 'h2':\r\n isActive = activeFormats.includes('header-2');\r\n break;\r\n case 'h3':\r\n isActive = activeFormats.includes('header-3');\r\n break;\r\n }\r\n\r\n button.classList.toggle('active', isActive);\r\n button.setAttribute('aria-pressed', isActive.toString());\r\n });\r\n } catch (error) {\r\n // Silently fail if markdown-actions not available\r\n }\r\n }\r\n\r\n /**\r\n * Destroy toolbar and cleanup\r\n */\r\n destroy() {\r\n if (this.container) {\r\n // Clean up event listeners\r\n if (this.handleDocumentClick) {\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n }\r\n\r\n // Clean up button listeners\r\n Object.values(this.buttons).forEach(button => {\r\n if (button._clickHandler) {\r\n button.removeEventListener('click', button._clickHandler);\r\n delete button._clickHandler;\r\n }\r\n });\r\n\r\n // Remove container\r\n this.container.remove();\r\n this.container = null;\r\n this.buttons = {};\r\n }\r\n }\r\n}\r\n", "/**\r\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\r\n * Shows a clickable tooltip when cursor is within a link\r\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\r\n */\r\n\r\nexport class LinkTooltip {\r\n constructor(editor) {\r\n this.editor = editor;\r\n this.tooltip = null;\r\n this.currentLink = null;\r\n this.hideTimeout = null;\r\n this.visibilityChangeHandler = null;\r\n this.useFloatingUI = false;\r\n this.floatingUI = null;\r\n this.isTooltipHovered = false;\r\n\r\n this.init();\r\n }\r\n\r\n async init() {\r\n // Detect CSS anchor positioning support\r\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\r\n CSS.supports('position-area: center');\r\n\r\n // Load Floating UI if needed\r\n if (!supportsAnchorPositioning) {\r\n try {\r\n // Use indirect eval to prevent bundler from processing the import\r\n const importFn = new Function('url', 'return import(url)');\r\n const { computePosition, offset, shift, flip } = await importFn(\r\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\r\n );\r\n this.floatingUI = { computePosition, offset, shift, flip };\r\n this.useFloatingUI = true;\r\n } catch (error) {\r\n // If dynamic import fails, tooltips simply won't show\r\n console.warn('Failed to load Floating UI fallback:', error);\r\n this.floatingUI = null;\r\n this.useFloatingUI = false;\r\n }\r\n }\r\n\r\n // Create tooltip element\r\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\r\n this.createTooltip();\r\n\r\n // Listen for cursor position changes\r\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\r\n this.editor.textarea.addEventListener('keyup', e => {\r\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\r\n this.checkCursorPosition();\r\n }\r\n });\r\n\r\n // Hide tooltip when typing\r\n this.editor.textarea.addEventListener('input', () => this.hide());\r\n\r\n // Reposition or hide tooltip when scrolling\r\n this.editor.textarea.addEventListener('scroll', () => {\r\n if (this.useFloatingUI && this.currentLink) {\r\n // Reposition the tooltip for Floating UI\r\n this.showWithFloatingUI(this.currentLink);\r\n } else {\r\n // Hide for CSS anchor positioning (native browser behavior handles this)\r\n this.hide();\r\n }\r\n });\r\n\r\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\r\n this.editor.textarea.addEventListener('blur', () => {\r\n if (!this.isTooltipHovered) {\r\n this.hide();\r\n }\r\n });\r\n\r\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\r\n this.visibilityChangeHandler = () => {\r\n if (document.hidden) {\r\n this.hide();\r\n }\r\n };\r\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\r\n\r\n // Track hover state to prevent hiding when clicking tooltip\r\n this.tooltip.addEventListener('mouseenter', () => {\r\n this.isTooltipHovered = true;\r\n this.cancelHide();\r\n });\r\n this.tooltip.addEventListener('mouseleave', () => {\r\n this.isTooltipHovered = false;\r\n this.scheduleHide();\r\n });\r\n }\r\n\r\n createTooltip() {\r\n // Create tooltip element\r\n // Styles are now included in the main stylesheet (styles.js)\r\n this.tooltip = document.createElement('div');\r\n this.tooltip.className = 'overtype-link-tooltip';\r\n\r\n // Add link icon and text container\r\n this.tooltip.innerHTML = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n `;\r\n\r\n // Click handler to open link\r\n this.tooltip.addEventListener('click', e => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (this.currentLink) {\r\n window.open(this.currentLink.url, '_blank');\r\n this.hide();\r\n }\r\n });\r\n\r\n // Append tooltip to editor container\r\n this.editor.container.appendChild(this.tooltip);\r\n }\r\n\r\n checkCursorPosition() {\r\n const cursorPos = this.editor.textarea.selectionStart;\r\n const text = this.editor.textarea.value;\r\n\r\n // Find if cursor is within a markdown link\r\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\r\n\r\n if (linkInfo) {\r\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\r\n this.show(linkInfo);\r\n }\r\n } else {\r\n this.scheduleHide();\r\n }\r\n }\r\n\r\n findLinkAtPosition(text, position) {\r\n // Regex to find markdown links: [text](url)\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n let match;\r\n let linkIndex = 0;\r\n\r\n while ((match = linkRegex.exec(text)) !== null) {\r\n const start = match.index;\r\n const end = match.index + match[0].length;\r\n\r\n if (position >= start && position <= end) {\r\n return {\r\n text: match[1],\r\n url: match[2],\r\n index: linkIndex,\r\n start: start,\r\n end: end\r\n };\r\n }\r\n linkIndex++;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n show(linkInfo) {\r\n this.currentLink = linkInfo;\r\n this.cancelHide();\r\n\r\n // Update tooltip content\r\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\r\n urlSpan.textContent = linkInfo.url;\r\n\r\n if (this.useFloatingUI) {\r\n this.showWithFloatingUI(linkInfo);\r\n } else {\r\n this.showWithAnchorPositioning(linkInfo);\r\n }\r\n\r\n this.tooltip.classList.add('visible');\r\n }\r\n\r\n showWithAnchorPositioning(linkInfo) {\r\n // Set the CSS variable to point to the correct anchor\r\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\r\n }\r\n\r\n async showWithFloatingUI(linkInfo) {\r\n // Find the element in preview that corresponds to this link\r\n const anchorElement = this.findAnchorElement(linkInfo.index);\r\n\r\n if (!anchorElement) {\r\n return;\r\n }\r\n\r\n // Check if anchor element is visible and in viewport\r\n const rect = anchorElement.getBoundingClientRect();\r\n if (rect.width === 0 || rect.height === 0) {\r\n return;\r\n }\r\n\r\n try {\r\n // Compute position using Floating UI\r\n const { x, y } = await this.floatingUI.computePosition(\r\n anchorElement,\r\n this.tooltip,\r\n {\r\n placement: 'bottom',\r\n middleware: [\r\n this.floatingUI.offset(8),\r\n this.floatingUI.shift({ padding: 8 }),\r\n this.floatingUI.flip()\r\n ]\r\n }\r\n );\r\n\r\n // Apply position\r\n Object.assign(this.tooltip.style, {\r\n left: `${x}px`,\r\n top: `${y}px`,\r\n position: 'absolute'\r\n });\r\n } catch (error) {\r\n // If Floating UI computation fails, don't show tooltip\r\n console.warn('Floating UI positioning failed:', error);\r\n return;\r\n }\r\n }\r\n\r\n findAnchorElement(linkIndex) {\r\n // Find the element with the matching anchor-name style\r\n const preview = this.editor.preview;\r\n // Direct query for the specific link - more efficient than iterating\r\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\r\n }\r\n\r\n hide() {\r\n this.tooltip.classList.remove('visible');\r\n this.currentLink = null;\r\n this.isTooltipHovered = false;\r\n }\r\n\r\n scheduleHide() {\r\n this.cancelHide();\r\n this.hideTimeout = setTimeout(() => this.hide(), 300);\r\n }\r\n\r\n cancelHide() {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n this.hideTimeout = null;\r\n }\r\n }\r\n\r\n destroy() {\r\n this.cancelHide();\r\n\r\n // Remove visibility change listener\r\n if (this.visibilityChangeHandler) {\r\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\r\n this.visibilityChangeHandler = null;\r\n }\r\n\r\n if (this.tooltip && this.tooltip.parentNode) {\r\n this.tooltip.parentNode.removeChild(this.tooltip);\r\n }\r\n this.tooltip = null;\r\n this.currentLink = null;\r\n this.floatingUI = null;\r\n this.useFloatingUI = false;\r\n this.isTooltipHovered = false;\r\n }\r\n}\r\n", "/**\r\n * SVG icons for OverType toolbar\r\n * Quill-style icons with inline styles\r\n */\r\n\r\nexport const boldIcon = `\r\n \r\n \r\n`;\r\n\r\nexport const italicIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\nexport const h1Icon = `\r\n \r\n`;\r\n\r\nexport const h2Icon = `\r\n \r\n`;\r\n\r\nexport const h3Icon = `\r\n \r\n`;\r\n\r\nexport const linkIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\nexport const codeIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\n\r\nexport const bulletListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const orderedListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const quoteIcon = `\r\n \r\n \r\n`;\r\n\r\nexport const taskListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const eyeIcon = `\r\n \r\n \r\n`;", "/**\r\n * Toolbar button definitions for OverType editor\r\n * Export built-in buttons that can be used in custom toolbar configurations\r\n */\r\n\r\nimport * as icons from './icons.js';\r\nimport * as markdownActions from 'markdown-actions';\r\n\r\n/**\r\n * Built-in toolbar button definitions\r\n * Each button has: name, actionId, icon, title, action\r\n * - name: DOM identifier for the button element\r\n * - actionId: Canonical action identifier used by performAction\r\n * Action signature: ({ editor, getValue, setValue, event }) => void\r\n */\r\nexport const toolbarButtons = {\r\n bold: {\r\n name: 'bold',\r\n actionId: 'toggleBold',\r\n icon: icons.boldIcon,\r\n title: 'Bold (Ctrl+B)',\r\n action: ({ editor }) => {\r\n markdownActions.toggleBold(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n italic: {\r\n name: 'italic',\r\n actionId: 'toggleItalic',\r\n icon: icons.italicIcon,\r\n title: 'Italic (Ctrl+I)',\r\n action: ({ editor }) => {\r\n markdownActions.toggleItalic(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n code: {\r\n name: 'code',\r\n actionId: 'toggleCode',\r\n icon: icons.codeIcon,\r\n title: 'Inline Code',\r\n action: ({ editor }) => {\r\n markdownActions.toggleCode(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n separator: {\r\n name: 'separator'\r\n // No icon, title, or action - special separator element\r\n },\r\n\r\n link: {\r\n name: 'link',\r\n actionId: 'insertLink',\r\n icon: icons.linkIcon,\r\n title: 'Insert Link',\r\n action: ({ editor }) => {\r\n markdownActions.insertLink(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h1: {\r\n name: 'h1',\r\n actionId: 'toggleH1',\r\n icon: icons.h1Icon,\r\n title: 'Heading 1',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH1(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h2: {\r\n name: 'h2',\r\n actionId: 'toggleH2',\r\n icon: icons.h2Icon,\r\n title: 'Heading 2',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH2(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h3: {\r\n name: 'h3',\r\n actionId: 'toggleH3',\r\n icon: icons.h3Icon,\r\n title: 'Heading 3',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH3(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n bulletList: {\r\n name: 'bulletList',\r\n actionId: 'toggleBulletList',\r\n icon: icons.bulletListIcon,\r\n title: 'Bullet List',\r\n action: ({ editor }) => {\r\n markdownActions.toggleBulletList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n orderedList: {\r\n name: 'orderedList',\r\n actionId: 'toggleNumberedList',\r\n icon: icons.orderedListIcon,\r\n title: 'Numbered List',\r\n action: ({ editor }) => {\r\n markdownActions.toggleNumberedList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n taskList: {\r\n name: 'taskList',\r\n actionId: 'toggleTaskList',\r\n icon: icons.taskListIcon,\r\n title: 'Task List',\r\n action: ({ editor }) => {\r\n if (markdownActions.toggleTaskList) {\r\n markdownActions.toggleTaskList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n }\r\n },\r\n\r\n quote: {\r\n name: 'quote',\r\n actionId: 'toggleQuote',\r\n icon: icons.quoteIcon,\r\n title: 'Quote',\r\n action: ({ editor }) => {\r\n markdownActions.toggleQuote(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n viewMode: {\r\n name: 'viewMode',\r\n icon: icons.eyeIcon,\r\n title: 'View mode'\r\n // Special: handled internally by Toolbar class as dropdown\r\n // No action property - dropdown behavior is internal\r\n }\r\n};\r\n\r\n/**\r\n * Default toolbar button layout with separators\r\n * This is used when toolbar: true but no toolbarButtons provided\r\n */\r\nexport const defaultToolbarButtons = [\r\n toolbarButtons.bold,\r\n toolbarButtons.italic,\r\n toolbarButtons.code,\r\n toolbarButtons.separator,\r\n toolbarButtons.link,\r\n toolbarButtons.separator,\r\n toolbarButtons.h1,\r\n toolbarButtons.h2,\r\n toolbarButtons.h3,\r\n toolbarButtons.separator,\r\n toolbarButtons.bulletList,\r\n toolbarButtons.orderedList,\r\n toolbarButtons.taskList,\r\n toolbarButtons.separator,\r\n toolbarButtons.quote,\r\n toolbarButtons.separator,\r\n toolbarButtons.viewMode\r\n];\r\n", "/**\r\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\r\n * @version 1.0.0\r\n * @license MIT\r\n */\r\n\r\nimport { MarkdownParser } from './parser.js';\r\nimport { ShortcutsManager } from './shortcuts.js';\r\nimport { generateStyles } from './styles.js';\r\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\r\nimport { Toolbar } from './toolbar.js';\r\nimport { LinkTooltip } from './link-tooltip.js';\r\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\r\n\r\n/**\r\n * Build action map from toolbar button configurations\r\n * @param {Array} buttons - Array of button config objects\r\n * @returns {Object} Map of actionId -> action function\r\n */\r\nfunction buildActionsMap(buttons) {\r\n const map = {};\r\n (buttons || []).forEach((btn) => {\r\n if (!btn || btn.name === 'separator') return;\r\n const id = btn.actionId || btn.name;\r\n if (btn.action) {\r\n map[id] = btn.action;\r\n }\r\n });\r\n return map;\r\n}\r\n\r\n/**\r\n * Normalize toolbar buttons for comparison\r\n * @param {Array|null} buttons\r\n * @returns {Array|null}\r\n */\r\nfunction normalizeButtons(buttons) {\r\n const list = buttons || defaultToolbarButtons;\r\n if (!Array.isArray(list)) return null;\r\n return list.map((btn) => ({\r\n name: btn?.name || null,\r\n actionId: btn?.actionId || btn?.name || null,\r\n icon: btn?.icon || null,\r\n title: btn?.title || null\r\n }));\r\n}\r\n\r\n/**\r\n * Determine if toolbar button configuration changed\r\n * @param {Array|null} prevButtons\r\n * @param {Array|null} nextButtons\r\n * @returns {boolean}\r\n */\r\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\r\n const prev = normalizeButtons(prevButtons);\r\n const next = normalizeButtons(nextButtons);\r\n\r\n if (prev === null || next === null) return prev !== next;\r\n if (prev.length !== next.length) return true;\r\n\r\n for (let i = 0; i < prev.length; i++) {\r\n const a = prev[i];\r\n const b = next[i];\r\n if (a.name !== b.name ||\r\n a.actionId !== b.actionId ||\r\n a.icon !== b.icon ||\r\n a.title !== b.title) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * OverType Editor Class\r\n */\r\nclass OverType {\r\n // Static properties\r\n static instances = new WeakMap();\r\n static stylesInjected = false;\r\n static globalListenersInitialized = false;\r\n static instanceCount = 0;\r\n static autoThemeMediaQuery = null; // Media query for auto theme switching\r\n static autoThemeListener = null; // Listener function for auto theme changes\r\n\r\n /**\r\n * Constructor - Always returns an array of instances\r\n * @param {string|Element|NodeList|Array} target - Target element(s)\r\n * @param {Object} options - Configuration options\r\n * @returns {Array} Array of OverType instances\r\n */\r\n constructor(target, options = {}) {\r\n // Convert target to array of elements\r\n let elements;\r\n \r\n if (typeof target === 'string') {\r\n elements = document.querySelectorAll(target);\r\n if (elements.length === 0) {\r\n throw new Error(`No elements found for selector: ${target}`);\r\n }\r\n elements = Array.from(elements);\r\n } else if (target instanceof Element) {\r\n elements = [target];\r\n } else if (target instanceof NodeList) {\r\n elements = Array.from(target);\r\n } else if (Array.isArray(target)) {\r\n elements = target;\r\n } else {\r\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\r\n }\r\n\r\n // Initialize all elements and return array\r\n const instances = elements.map(element => {\r\n // Check for existing instance\r\n if (element.overTypeInstance) {\r\n // Re-init existing instance\r\n element.overTypeInstance.reinit(options);\r\n return element.overTypeInstance;\r\n }\r\n\r\n // Create new instance\r\n const instance = Object.create(OverType.prototype);\r\n instance._init(element, options);\r\n element.overTypeInstance = instance;\r\n OverType.instances.set(element, instance);\r\n return instance;\r\n });\r\n\r\n return instances;\r\n }\r\n\r\n /**\r\n * Internal initialization\r\n * @private\r\n */\r\n _init(element, options = {}) {\r\n this.element = element;\r\n \r\n // Store the original theme option before merging\r\n this.instanceTheme = options.theme || null;\r\n \r\n // Auto theme tracking for instance-level theme\r\n this.autoThemeMediaQuery = null;\r\n this.autoThemeListener = null;\r\n \r\n this.options = this._mergeOptions(options);\r\n this.instanceId = ++OverType.instanceCount;\r\n this.initialized = false;\r\n\r\n // Inject styles if needed\r\n OverType.injectStyles();\r\n\r\n // Initialize global listeners\r\n OverType.initGlobalListeners();\r\n\r\n // Check for existing OverType DOM structure\r\n const container = element.querySelector('.overtype-container');\r\n const wrapper = element.querySelector('.overtype-wrapper');\r\n if (container || wrapper) {\r\n this._recoverFromDOM(container, wrapper);\r\n } else {\r\n this._buildFromScratch();\r\n }\r\n\r\n // Set up instance theme if provided (including auto theme listener)\r\n if (this.instanceTheme) {\r\n this.setTheme(this.instanceTheme);\r\n }\r\n\r\n // Setup shortcuts manager\r\n this.shortcuts = new ShortcutsManager(this);\r\n\r\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\r\n this._rebuildActionsMap();\r\n\r\n // Setup link tooltip\r\n this.linkTooltip = new LinkTooltip(this);\r\n\r\n // Sync scroll positions on initial render\r\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\r\n // Double requestAnimationFrame waits for browser to restore scroll position\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(() => {\r\n this.textarea.scrollTop = this.preview.scrollTop;\r\n this.textarea.scrollLeft = this.preview.scrollLeft;\r\n });\r\n });\r\n\r\n // Mark as initialized\r\n this.initialized = true;\r\n\r\n // Call onChange if provided\r\n if (this.options.onChange) {\r\n this.options.onChange(this.getValue(), this);\r\n }\r\n }\r\n\r\n /**\r\n * Merge user options with defaults\r\n * @private\r\n */\r\n _mergeOptions(options) {\r\n const defaults = {\r\n // Typography\r\n fontSize: '14px',\r\n lineHeight: 1.6,\r\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\r\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\r\n padding: '16px',\r\n \r\n // Mobile styles\r\n mobile: {\r\n fontSize: '16px', // Prevent zoom on iOS\r\n padding: '12px',\r\n lineHeight: 1.5\r\n },\r\n \r\n // Native textarea properties\r\n textareaProps: {},\r\n \r\n // Behavior\r\n autofocus: false,\r\n autoResize: false, // Auto-expand height with content\r\n minHeight: '100px', // Minimum height for autoResize mode\r\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\r\n placeholder: 'Start typing...',\r\n value: '',\r\n \r\n // Callbacks\r\n onChange: null,\r\n onKeydown: null,\r\n \r\n // Features\r\n showActiveLineRaw: false,\r\n showStats: false,\r\n toolbar: false,\r\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\r\n statsFormatter: null,\r\n smartLists: true, // Enable smart list continuation\r\n codeHighlighter: null // Per-instance code highlighter\r\n };\r\n \r\n // Remove theme and colors from options - these are now global\r\n const { theme, colors, ...cleanOptions } = options;\r\n \r\n return {\r\n ...defaults,\r\n ...cleanOptions\r\n };\r\n }\r\n\r\n /**\r\n * Recover from existing DOM structure\r\n * @private\r\n */\r\n _recoverFromDOM(container, wrapper) {\r\n // Handle old structure (wrapper only) or new structure (container + wrapper)\r\n if (container && container.classList.contains('overtype-container')) {\r\n this.container = container;\r\n this.wrapper = container.querySelector('.overtype-wrapper');\r\n } else if (wrapper) {\r\n // Old structure - just wrapper, no container\r\n this.wrapper = wrapper;\r\n // Wrap it in a container for consistency\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-container';\r\n // Use instance theme if provided, otherwise use global theme\r\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\r\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\r\n if (themeName) {\r\n this.container.setAttribute('data-theme', themeName);\r\n }\r\n \r\n // If using instance theme, apply CSS variables to container\r\n if (this.instanceTheme) {\r\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\r\n if (themeObj && themeObj.colors) {\r\n const cssVars = themeToCSSVars(themeObj.colors);\r\n this.container.style.cssText += cssVars;\r\n }\r\n }\r\n wrapper.parentNode.insertBefore(this.container, wrapper);\r\n this.container.appendChild(wrapper);\r\n }\r\n \r\n if (!this.wrapper) {\r\n // No valid structure found\r\n if (container) container.remove();\r\n if (wrapper) wrapper.remove();\r\n this._buildFromScratch();\r\n return;\r\n }\r\n \r\n this.textarea = this.wrapper.querySelector('.overtype-input');\r\n this.preview = this.wrapper.querySelector('.overtype-preview');\r\n\r\n if (!this.textarea || !this.preview) {\r\n // Partial DOM - clear and rebuild\r\n this.container.remove();\r\n this._buildFromScratch();\r\n return;\r\n }\r\n\r\n // Store reference on wrapper\r\n this.wrapper._instance = this;\r\n \r\n // Apply instance-specific styles via CSS custom properties\r\n if (this.options.fontSize) {\r\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\r\n }\r\n if (this.options.lineHeight) {\r\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\r\n }\r\n if (this.options.padding) {\r\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\r\n }\r\n\r\n // Disable autofill, spellcheck, and extensions\r\n this._configureTextarea();\r\n\r\n // Apply any new options\r\n this._applyOptions();\r\n }\r\n\r\n /**\r\n * Build editor from scratch\r\n * @private\r\n */\r\n _buildFromScratch() {\r\n // Extract any existing content\r\n const content = this._extractContent();\r\n\r\n // Clear element\r\n this.element.innerHTML = '';\r\n\r\n // Create DOM structure\r\n this._createDOM();\r\n\r\n // Set initial content\r\n if (content || this.options.value) {\r\n this.setValue(content || this.options.value);\r\n }\r\n\r\n // Apply options\r\n this._applyOptions();\r\n }\r\n\r\n /**\r\n * Extract content from element\r\n * @private\r\n */\r\n _extractContent() {\r\n // Look for existing OverType textarea\r\n const textarea = this.element.querySelector('.overtype-input');\r\n if (textarea) return textarea.value;\r\n\r\n // Use element's text content as fallback\r\n return this.element.textContent || '';\r\n }\r\n\r\n /**\r\n * Create DOM structure\r\n * @private\r\n */\r\n _createDOM() {\r\n // Create container that will hold toolbar and editor\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-container';\r\n \r\n // Set theme on container - use instance theme if provided\r\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\r\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\r\n if (themeName) {\r\n this.container.setAttribute('data-theme', themeName);\r\n }\r\n \r\n // If using instance theme, apply CSS variables to container\r\n if (this.instanceTheme) {\r\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\r\n if (themeObj && themeObj.colors) {\r\n const cssVars = themeToCSSVars(themeObj.colors);\r\n this.container.style.cssText += cssVars;\r\n }\r\n }\r\n \r\n // Create wrapper for editor\r\n this.wrapper = document.createElement('div');\r\n this.wrapper.className = 'overtype-wrapper';\r\n \r\n \r\n // Apply instance-specific styles via CSS custom properties\r\n if (this.options.fontSize) {\r\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\r\n }\r\n if (this.options.lineHeight) {\r\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\r\n }\r\n if (this.options.padding) {\r\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\r\n }\r\n \r\n this.wrapper._instance = this;\r\n\r\n // Create textarea\r\n this.textarea = document.createElement('textarea');\r\n this.textarea.className = 'overtype-input';\r\n this.textarea.placeholder = this.options.placeholder;\r\n this._configureTextarea();\r\n \r\n // Apply any native textarea properties\r\n if (this.options.textareaProps) {\r\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\r\n if (key === 'className' || key === 'class') {\r\n this.textarea.className += ' ' + value;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n Object.assign(this.textarea.style, value);\r\n } else {\r\n this.textarea.setAttribute(key, value);\r\n }\r\n });\r\n }\r\n\r\n // Create preview div\r\n this.preview = document.createElement('div');\r\n this.preview.className = 'overtype-preview';\r\n this.preview.setAttribute('aria-hidden', 'true');\r\n\r\n // Assemble DOM\r\n this.wrapper.appendChild(this.textarea);\r\n this.wrapper.appendChild(this.preview);\r\n \r\n // No need to prevent link clicks - pointer-events handles this\r\n \r\n // Add wrapper to container first\r\n this.container.appendChild(this.wrapper);\r\n \r\n // Add stats bar at the end (bottom) if enabled\r\n if (this.options.showStats) {\r\n this.statsBar = document.createElement('div');\r\n this.statsBar.className = 'overtype-stats';\r\n this.container.appendChild(this.statsBar);\r\n this._updateStats();\r\n }\r\n \r\n // Add container to element\r\n this.element.appendChild(this.container);\r\n \r\n // Setup auto-resize if enabled\r\n if (this.options.autoResize) {\r\n this._setupAutoResize();\r\n } else {\r\n // Ensure auto-resize class is removed if not using auto-resize\r\n this.container.classList.remove('overtype-auto-resize');\r\n }\r\n }\r\n\r\n /**\r\n * Configure textarea attributes\r\n * @private\r\n */\r\n _configureTextarea() {\r\n this.textarea.setAttribute('autocomplete', 'off');\r\n this.textarea.setAttribute('autocorrect', 'off');\r\n this.textarea.setAttribute('autocapitalize', 'off');\r\n this.textarea.setAttribute('spellcheck', 'false');\r\n this.textarea.setAttribute('data-gramm', 'false');\r\n this.textarea.setAttribute('data-gramm_editor', 'false');\r\n this.textarea.setAttribute('data-enable-grammarly', 'false');\r\n }\r\n\r\n /**\r\n * Create and setup toolbar\r\n * @private\r\n */\r\n _createToolbar() {\r\n // Use provided toolbarButtons or default to defaultToolbarButtons\r\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\r\n\r\n this.toolbar = new Toolbar(this, { toolbarButtons });\r\n this.toolbar.create();\r\n\r\n // Store listener references for cleanup\r\n this._toolbarSelectionListener = () => {\r\n if (this.toolbar) {\r\n this.toolbar.updateButtonStates();\r\n }\r\n };\r\n this._toolbarInputListener = () => {\r\n if (this.toolbar) {\r\n this.toolbar.updateButtonStates();\r\n }\r\n };\r\n\r\n // Add listeners\r\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\r\n this.textarea.addEventListener('input', this._toolbarInputListener);\r\n }\r\n\r\n /**\r\n * Cleanup toolbar event listeners\r\n * @private\r\n */\r\n _cleanupToolbarListeners() {\r\n if (this._toolbarSelectionListener) {\r\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\r\n this._toolbarSelectionListener = null;\r\n }\r\n if (this._toolbarInputListener) {\r\n this.textarea.removeEventListener('input', this._toolbarInputListener);\r\n this._toolbarInputListener = null;\r\n }\r\n }\r\n\r\n /**\r\n * Rebuild the action map from current toolbar button configuration\r\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\r\n * @private\r\n */\r\n _rebuildActionsMap() {\r\n // Always start with default actions (shortcuts always work regardless of toolbar config)\r\n this.actionsById = buildActionsMap(defaultToolbarButtons);\r\n\r\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\r\n if (this.options.toolbarButtons) {\r\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\r\n }\r\n }\r\n\r\n /**\r\n * Apply options to the editor\r\n * @private\r\n */\r\n _applyOptions() {\r\n // Apply autofocus\r\n if (this.options.autofocus) {\r\n this.textarea.focus();\r\n }\r\n\r\n // Setup or remove auto-resize\r\n if (this.options.autoResize) {\r\n if (!this.container.classList.contains('overtype-auto-resize')) {\r\n this._setupAutoResize();\r\n }\r\n } else {\r\n // Ensure auto-resize class is removed\r\n this.container.classList.remove('overtype-auto-resize');\r\n }\r\n\r\n // Handle toolbar option changes\r\n if (this.options.toolbar && !this.toolbar) {\r\n // Create toolbar if enabled and doesn't exist\r\n this._createToolbar();\r\n } else if (!this.options.toolbar && this.toolbar) {\r\n // Destroy toolbar if disabled and exists\r\n this._cleanupToolbarListeners();\r\n this.toolbar.destroy();\r\n this.toolbar = null;\r\n }\r\n\r\n // Update preview with initial content\r\n this.updatePreview();\r\n }\r\n\r\n /**\r\n * Update preview with parsed markdown\r\n */\r\n updatePreview() {\r\n const text = this.textarea.value;\r\n const cursorPos = this.textarea.selectionStart;\r\n const activeLine = this._getCurrentLine(text, cursorPos);\r\n\r\n // Detect if we're in preview mode\r\n const isPreviewMode = this.container.dataset.mode === 'preview';\r\n\r\n // Parse markdown\r\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\r\n this.preview.innerHTML = html || 'Start typing...';\r\n \r\n // Apply code block backgrounds\r\n this._applyCodeBlockBackgrounds();\r\n \r\n // Links always have real hrefs now - no need to update them\r\n \r\n // Update stats if enabled\r\n if (this.options.showStats && this.statsBar) {\r\n this._updateStats();\r\n }\r\n \r\n // Trigger onChange callback\r\n if (this.options.onChange && this.initialized) {\r\n this.options.onChange(text, this);\r\n }\r\n }\r\n\r\n /**\r\n * Apply background styling to code blocks\r\n * @private\r\n */\r\n _applyCodeBlockBackgrounds() {\r\n // Find all code fence elements\r\n const codeFences = this.preview.querySelectorAll('.code-fence');\r\n \r\n // Process pairs of code fences\r\n for (let i = 0; i < codeFences.length - 1; i += 2) {\r\n const openFence = codeFences[i];\r\n const closeFence = codeFences[i + 1];\r\n \r\n // Get parent divs\r\n const openParent = openFence.parentElement;\r\n const closeParent = closeFence.parentElement;\r\n \r\n if (!openParent || !closeParent) continue;\r\n \r\n // Make fences display: block\r\n openFence.style.display = 'block';\r\n closeFence.style.display = 'block';\r\n \r\n // Apply class to parent divs\r\n openParent.classList.add('code-block-line');\r\n closeParent.classList.add('code-block-line');\r\n \r\n // With the new structure, there's a
     block between fences, not DIVs\r\n        // We don't need to process anything between the fences anymore\r\n        // The 
     structure already handles the content correctly\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Get current line number from cursor position\r\n     * @private\r\n     */\r\n    _getCurrentLine(text, cursorPos) {\r\n      const lines = text.substring(0, cursorPos).split('\\n');\r\n      return lines.length - 1;\r\n    }\r\n\r\n    /**\r\n     * Handle input events\r\n     * @private\r\n     */\r\n    handleInput(event) {\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Handle keydown events\r\n     * @private\r\n     */\r\n    handleKeydown(event) {\r\n      // Handle Tab key to prevent focus loss and insert spaces\r\n      if (event.key === 'Tab') {\r\n        const start = this.textarea.selectionStart;\r\n        const end = this.textarea.selectionEnd;\r\n        const value = this.textarea.value;\r\n\r\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\r\n        if (event.shiftKey && start === end) {\r\n          return;\r\n        }\r\n\r\n        event.preventDefault();\r\n\r\n        // If there's a selection, indent/outdent based on shift key\r\n        if (start !== end && event.shiftKey) {\r\n          // Outdent: remove 2 spaces from start of each selected line\r\n          const before = value.substring(0, start);\r\n          const selection = value.substring(start, end);\r\n          const after = value.substring(end);\r\n          \r\n          const lines = selection.split('\\n');\r\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\r\n          \r\n          // Try to use execCommand first to preserve undo history\r\n          if (document.execCommand) {\r\n            // Select the text that needs to be replaced\r\n            this.textarea.setSelectionRange(start, end);\r\n            document.execCommand('insertText', false, outdented);\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = before + outdented + after;\r\n            this.textarea.selectionStart = start;\r\n            this.textarea.selectionEnd = start + outdented.length;\r\n          }\r\n        } else if (start !== end) {\r\n          // Indent: add 2 spaces to start of each selected line\r\n          const before = value.substring(0, start);\r\n          const selection = value.substring(start, end);\r\n          const after = value.substring(end);\r\n          \r\n          const lines = selection.split('\\n');\r\n          const indented = lines.map(line => '  ' + line).join('\\n');\r\n          \r\n          // Try to use execCommand first to preserve undo history\r\n          if (document.execCommand) {\r\n            // Select the text that needs to be replaced\r\n            this.textarea.setSelectionRange(start, end);\r\n            document.execCommand('insertText', false, indented);\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = before + indented + after;\r\n            this.textarea.selectionStart = start;\r\n            this.textarea.selectionEnd = start + indented.length;\r\n          }\r\n        } else {\r\n          // No selection: just insert 2 spaces\r\n          // Use execCommand to preserve undo history\r\n          if (document.execCommand) {\r\n            document.execCommand('insertText', false, '  ');\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\r\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\r\n          }\r\n        }\r\n        \r\n        // Trigger input event to update preview\r\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n        return;\r\n      }\r\n      \r\n      // Handle Enter key for smart list continuation\r\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\r\n        if (this.handleSmartListContinuation()) {\r\n          event.preventDefault();\r\n          return;\r\n        }\r\n      }\r\n      \r\n      // Let shortcuts manager handle other keys\r\n      const handled = this.shortcuts.handleKeydown(event);\r\n      \r\n      // Call user callback if provided\r\n      if (!handled && this.options.onKeydown) {\r\n        this.options.onKeydown(event, this);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Handle smart list continuation\r\n     * @returns {boolean} Whether the event was handled\r\n     */\r\n    handleSmartListContinuation() {\r\n      const textarea = this.textarea;\r\n      const cursorPos = textarea.selectionStart;\r\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\r\n      \r\n      if (!context || !context.inList) return false;\r\n      \r\n      // Handle empty list item (exit list)\r\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\r\n        this.deleteListMarker(context);\r\n        return true;\r\n      }\r\n      \r\n      // Handle text splitting if cursor is in middle of content\r\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\r\n        this.splitListItem(context, cursorPos);\r\n      } else {\r\n        // Just add new item after current line\r\n        this.insertNewListItem(context);\r\n      }\r\n      \r\n      // Handle numbered list renumbering\r\n      if (context.listType === 'numbered') {\r\n        this.scheduleNumberedListUpdate();\r\n      }\r\n      \r\n      return true;\r\n    }\r\n    \r\n    /**\r\n     * Delete list marker and exit list\r\n     * @private\r\n     */\r\n    deleteListMarker(context) {\r\n      // Select from line start to marker end\r\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\r\n      document.execCommand('delete');\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Insert new list item\r\n     * @private\r\n     */\r\n    insertNewListItem(context) {\r\n      const newItem = MarkdownParser.createNewListItem(context);\r\n      document.execCommand('insertText', false, '\\n' + newItem);\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Split list item at cursor position\r\n     * @private\r\n     */\r\n    splitListItem(context, cursorPos) {\r\n      // Get text after cursor\r\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\r\n      \r\n      // Delete text after cursor\r\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\r\n      document.execCommand('delete');\r\n      \r\n      // Insert new list item with remaining text\r\n      const newItem = MarkdownParser.createNewListItem(context);\r\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\r\n      \r\n      // Position cursor after new list marker\r\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\r\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Schedule numbered list renumbering\r\n     * @private\r\n     */\r\n    scheduleNumberedListUpdate() {\r\n      // Clear any pending update\r\n      if (this.numberUpdateTimeout) {\r\n        clearTimeout(this.numberUpdateTimeout);\r\n      }\r\n      \r\n      // Schedule update after current input cycle\r\n      this.numberUpdateTimeout = setTimeout(() => {\r\n        this.updateNumberedLists();\r\n      }, 10);\r\n    }\r\n    \r\n    /**\r\n     * Update/renumber all numbered lists\r\n     * @private\r\n     */\r\n    updateNumberedLists() {\r\n      const value = this.textarea.value;\r\n      const cursorPos = this.textarea.selectionStart;\r\n      \r\n      const newValue = MarkdownParser.renumberLists(value);\r\n      \r\n      if (newValue !== value) {\r\n        // Calculate cursor offset\r\n        let offset = 0;\r\n        const oldLines = value.split('\\n');\r\n        const newLines = newValue.split('\\n');\r\n        let charCount = 0;\r\n        \r\n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\r\n          if (oldLines[i] !== newLines[i]) {\r\n            const diff = newLines[i].length - oldLines[i].length;\r\n            if (charCount + oldLines[i].length < cursorPos) {\r\n              offset += diff;\r\n            }\r\n          }\r\n          charCount += oldLines[i].length + 1; // +1 for newline\r\n        }\r\n        \r\n        // Update textarea\r\n        this.textarea.value = newValue;\r\n        const newCursorPos = cursorPos + offset;\r\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\r\n        \r\n        // Trigger update\r\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Handle scroll events\r\n     * @private\r\n     */\r\n    handleScroll(event) {\r\n      // Sync preview scroll with textarea\r\n      this.preview.scrollTop = this.textarea.scrollTop;\r\n      this.preview.scrollLeft = this.textarea.scrollLeft;\r\n    }\r\n\r\n    /**\r\n     * Get editor content\r\n     * @returns {string} Current markdown content\r\n     */\r\n    getValue() {\r\n      return this.textarea.value;\r\n    }\r\n\r\n    /**\r\n     * Set editor content\r\n     * @param {string} value - Markdown content to set\r\n     */\r\n    setValue(value) {\r\n      this.textarea.value = value;\r\n      this.updatePreview();\r\n\r\n      // Update height if auto-resize is enabled\r\n      if (this.options.autoResize) {\r\n        this._updateAutoHeight();\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Execute an action by ID\r\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\r\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\r\n     * @param {Event|null} event - Optional event that triggered the action\r\n     * @returns {Promise} Whether the action was executed successfully\r\n     */\r\n    async performAction(actionId, event = null) {\r\n      const textarea = this.textarea;\r\n      if (!textarea) return false;\r\n\r\n      const action = this.actionsById?.[actionId];\r\n      if (!action) {\r\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\r\n        return false;\r\n      }\r\n\r\n      textarea.focus();\r\n\r\n      try {\r\n        await action({\r\n          editor: this,\r\n          getValue: () => this.getValue(),\r\n          setValue: (value) => this.setValue(value),\r\n          event\r\n        });\r\n        // Note: actions are responsible for dispatching input event\r\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\r\n        return true;\r\n      } catch (error) {\r\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\r\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\r\n          detail: { actionId, error }\r\n        }));\r\n        return false;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Get the rendered HTML of the current content\r\n     * @param {Object} options - Rendering options\r\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\r\n     * @returns {string} Rendered HTML\r\n     */\r\n    getRenderedHTML(options = {}) {\r\n      const markdown = this.getValue();\r\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\r\n\r\n      if (options.cleanHTML) {\r\n        // Remove all syntax marker spans for clean HTML export\r\n        html = html.replace(/.*?<\\/span>/g, '');\r\n        // Remove OverType-specific classes\r\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\r\n        // Clean up empty class attributes\r\n        html = html.replace(/\\sclass=\"\"/g, '');\r\n      }\r\n      \r\n      return html;\r\n    }\r\n\r\n    /**\r\n     * Get the current preview element's HTML\r\n     * This includes all syntax markers and OverType styling\r\n     * @returns {string} Current preview HTML (as displayed)\r\n     */\r\n    getPreviewHTML() {\r\n      return this.preview.innerHTML;\r\n    }\r\n    \r\n    /**\r\n     * Get clean HTML without any OverType-specific markup\r\n     * Useful for exporting to other formats or storage\r\n     * @returns {string} Clean HTML suitable for export\r\n     */\r\n    getCleanHTML() {\r\n      return this.getRenderedHTML({ cleanHTML: true });\r\n    }\r\n\r\n    /**\r\n     * Focus the editor\r\n     */\r\n    focus() {\r\n      this.textarea.focus();\r\n    }\r\n\r\n    /**\r\n     * Blur the editor\r\n     */\r\n    blur() {\r\n      this.textarea.blur();\r\n    }\r\n\r\n    /**\r\n     * Check if editor is initialized\r\n     * @returns {boolean}\r\n     */\r\n    isInitialized() {\r\n      return this.initialized;\r\n    }\r\n\r\n    /**\r\n     * Re-initialize with new options\r\n     * @param {Object} options - New options to apply\r\n     */\r\n    reinit(options = {}) {\r\n      const prevToolbarButtons = this.options?.toolbarButtons;\r\n      this.options = this._mergeOptions({ ...this.options, ...options });\r\n      const toolbarNeedsRebuild = this.toolbar &&\r\n        this.options.toolbar &&\r\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\r\n\r\n      // Rebuild action map in case toolbarButtons changed\r\n      this._rebuildActionsMap();\r\n\r\n      if (toolbarNeedsRebuild) {\r\n        this._cleanupToolbarListeners();\r\n        this.toolbar.destroy();\r\n        this.toolbar = null;\r\n        this._createToolbar();\r\n      }\r\n\r\n      this._applyOptions();\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Set theme for this instance\r\n     * @param {string|Object} theme - Theme name or custom theme object\r\n     * @returns {this} Returns this for chaining\r\n     */\r\n    setTheme(theme) {\r\n      // Clean up existing auto theme listener if any\r\n      this._cleanupAutoThemeListener();\r\n\r\n      // Update instance theme\r\n      this.instanceTheme = theme;\r\n\r\n      // Handle auto theme\r\n      if (theme === 'auto') {\r\n        this._setupAutoThemeListener();\r\n        // Apply the initial resolved theme\r\n        const resolvedTheme = resolveAutoTheme('auto');\r\n        this._applyResolvedTheme(resolvedTheme);\r\n      } else {\r\n        // Get theme object for non-auto themes\r\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\r\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n\r\n        // Update container theme attribute\r\n        if (themeName) {\r\n          this.container.setAttribute('data-theme', themeName);\r\n        }\r\n\r\n        // Apply CSS variables to container for instance override\r\n        if (themeObj && themeObj.colors) {\r\n          const cssVars = themeToCSSVars(themeObj.colors);\r\n          this.container.style.cssText += cssVars;\r\n        }\r\n\r\n        // Update preview to reflect new theme\r\n        this.updatePreview();\r\n      }\r\n\r\n      return this;\r\n    }\r\n\r\n    /**\r\n     * Apply a resolved theme name (used by auto theme)\r\n     * @private\r\n     * @param {string} themeName - Resolved theme name\r\n     */\r\n    _applyResolvedTheme(themeName) {\r\n      const themeObj = getTheme(themeName);\r\n      \r\n      // Update container with resolved theme, but keep auto in data-theme for tracking\r\n      this.container.setAttribute('data-theme', 'auto');\r\n      this.container.setAttribute('data-resolved-theme', themeName);\r\n\r\n      // Apply CSS variables\r\n      if (themeObj && themeObj.colors) {\r\n        const cssVars = themeToCSSVars(themeObj.colors);\r\n        this.container.style.cssText += cssVars;\r\n      }\r\n\r\n      // Update preview to reflect new theme\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Setup auto theme listener for instance\r\n     * @private\r\n     */\r\n    _setupAutoThemeListener() {\r\n      if (!window.matchMedia) return;\r\n\r\n      this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n      this.autoThemeListener = (event) => {\r\n        const resolvedTheme = event.matches ? 'cave' : 'solar';\r\n        this._applyResolvedTheme(resolvedTheme);\r\n      };\r\n\r\n      // Use addEventListener if available (modern browsers)\r\n      if (this.autoThemeMediaQuery.addEventListener) {\r\n        this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener);\r\n      } else if (this.autoThemeMediaQuery.addListener) {\r\n        // Fallback for older browsers\r\n        this.autoThemeMediaQuery.addListener(this.autoThemeListener);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Clean up auto theme listener for instance\r\n     * @private\r\n     */\r\n    _cleanupAutoThemeListener() {\r\n      if (this.autoThemeMediaQuery && this.autoThemeListener) {\r\n        if (this.autoThemeMediaQuery.removeEventListener) {\r\n          this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener);\r\n        } else if (this.autoThemeMediaQuery.removeListener) {\r\n          // Fallback for older browsers\r\n          this.autoThemeMediaQuery.removeListener(this.autoThemeListener);\r\n        }\r\n        this.autoThemeMediaQuery = null;\r\n        this.autoThemeListener = null;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Set instance-specific code highlighter\r\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n     */\r\n    setCodeHighlighter(highlighter) {\r\n      this.options.codeHighlighter = highlighter;\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Update stats bar\r\n     * @private\r\n     */\r\n    _updateStats() {\r\n      if (!this.statsBar) return;\r\n      \r\n      const value = this.textarea.value;\r\n      const lines = value.split('\\n');\r\n      const chars = value.length;\r\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\r\n      \r\n      // Calculate line and column\r\n      const selectionStart = this.textarea.selectionStart;\r\n      const beforeCursor = value.substring(0, selectionStart);\r\n      const linesBeforeCursor = beforeCursor.split('\\n');\r\n      const currentLine = linesBeforeCursor.length;\r\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\r\n      \r\n      // Use custom formatter if provided\r\n      if (this.options.statsFormatter) {\r\n        this.statsBar.innerHTML = this.options.statsFormatter({\r\n          chars,\r\n          words,\r\n          lines: lines.length,\r\n          line: currentLine,\r\n          column: currentColumn\r\n        });\r\n      } else {\r\n        // Default format with live dot\r\n        this.statsBar.innerHTML = `\r\n          
    \r\n \r\n ${chars} chars, ${words} words, ${lines.length} lines\r\n
    \r\n
    Line ${currentLine}, Col ${currentColumn}
    \r\n `;\r\n }\r\n }\r\n \r\n /**\r\n * Setup auto-resize functionality\r\n * @private\r\n */\r\n _setupAutoResize() {\r\n // Add auto-resize class for styling\r\n this.container.classList.add('overtype-auto-resize');\r\n \r\n // Store previous height for comparison\r\n this.previousHeight = null;\r\n \r\n // Initial height update\r\n this._updateAutoHeight();\r\n \r\n // Listen for input events\r\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\r\n \r\n // Listen for window resize\r\n window.addEventListener('resize', () => this._updateAutoHeight());\r\n }\r\n \r\n /**\r\n * Update height based on scrollHeight\r\n * @private\r\n */\r\n _updateAutoHeight() {\r\n if (!this.options.autoResize) return;\r\n \r\n const textarea = this.textarea;\r\n const preview = this.preview;\r\n const wrapper = this.wrapper;\r\n \r\n // Get computed styles\r\n const computed = window.getComputedStyle(textarea);\r\n const paddingTop = parseFloat(computed.paddingTop);\r\n const paddingBottom = parseFloat(computed.paddingBottom);\r\n \r\n // Store scroll positions\r\n const scrollTop = textarea.scrollTop;\r\n \r\n // Reset height to get accurate scrollHeight\r\n textarea.style.setProperty('height', 'auto', 'important');\r\n \r\n // Calculate new height based on scrollHeight\r\n let newHeight = textarea.scrollHeight;\r\n \r\n // Apply min height constraint\r\n if (this.options.minHeight) {\r\n const minHeight = parseInt(this.options.minHeight);\r\n newHeight = Math.max(newHeight, minHeight);\r\n }\r\n \r\n // Apply max height constraint\r\n let overflow = 'hidden';\r\n if (this.options.maxHeight) {\r\n const maxHeight = parseInt(this.options.maxHeight);\r\n if (newHeight > maxHeight) {\r\n newHeight = maxHeight;\r\n overflow = 'auto';\r\n }\r\n }\r\n \r\n // Apply the new height to all elements with !important to override base styles\r\n const heightPx = newHeight + 'px';\r\n textarea.style.setProperty('height', heightPx, 'important');\r\n textarea.style.setProperty('overflow-y', overflow, 'important');\r\n \r\n preview.style.setProperty('height', heightPx, 'important');\r\n preview.style.setProperty('overflow-y', overflow, 'important');\r\n \r\n wrapper.style.setProperty('height', heightPx, 'important');\r\n \r\n // Restore scroll position\r\n textarea.scrollTop = scrollTop;\r\n preview.scrollTop = scrollTop;\r\n \r\n // Track if height changed\r\n if (this.previousHeight !== newHeight) {\r\n this.previousHeight = newHeight;\r\n // Could dispatch a custom event here if needed\r\n }\r\n }\r\n \r\n /**\r\n * Show or hide stats bar\r\n * @param {boolean} show - Whether to show stats\r\n */\r\n showStats(show) {\r\n this.options.showStats = show;\r\n\r\n if (show && !this.statsBar) {\r\n // Create stats bar (add to container, not wrapper)\r\n this.statsBar = document.createElement('div');\r\n this.statsBar.className = 'overtype-stats';\r\n this.container.appendChild(this.statsBar);\r\n this._updateStats();\r\n } else if (show && this.statsBar) {\r\n // Already visible - refresh stats (useful after changing statsFormatter)\r\n this._updateStats();\r\n } else if (!show && this.statsBar) {\r\n // Remove stats bar\r\n this.statsBar.remove();\r\n this.statsBar = null;\r\n }\r\n }\r\n \r\n /**\r\n * Show normal edit mode (overlay with markdown preview)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showNormalEditMode() {\r\n this.container.dataset.mode = 'normal';\r\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\r\n\r\n // Always sync scroll from preview to textarea\r\n requestAnimationFrame(() => {\r\n this.textarea.scrollTop = this.preview.scrollTop;\r\n this.textarea.scrollLeft = this.preview.scrollLeft;\r\n });\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Show plain textarea mode (no overlay)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showPlainTextarea() {\r\n this.container.dataset.mode = 'plain';\r\n\r\n // Update toolbar button if exists\r\n if (this.toolbar) {\r\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\r\n if (toggleBtn) {\r\n toggleBtn.classList.remove('active');\r\n toggleBtn.title = 'Show markdown preview';\r\n }\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Show preview mode (read-only view)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showPreviewMode() {\r\n this.container.dataset.mode = 'preview';\r\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\r\n return this;\r\n }\r\n\r\n /**\r\n * Destroy the editor instance\r\n */\r\n destroy() {\r\n // Clean up auto theme listener\r\n this._cleanupAutoThemeListener();\r\n\r\n // Remove instance reference\r\n this.element.overTypeInstance = null;\r\n OverType.instances.delete(this.element);\r\n\r\n // Cleanup shortcuts\r\n if (this.shortcuts) {\r\n this.shortcuts.destroy();\r\n }\r\n\r\n // Remove DOM if created by us\r\n if (this.wrapper) {\r\n const content = this.getValue();\r\n this.wrapper.remove();\r\n \r\n // Restore original content\r\n this.element.textContent = content;\r\n }\r\n\r\n this.initialized = false;\r\n }\r\n\r\n // ===== Static Methods =====\r\n\r\n /**\r\n * Initialize multiple editors (static convenience method)\r\n * @param {string|Element|NodeList|Array} target - Target element(s)\r\n * @param {Object} options - Configuration options\r\n * @returns {Array} Array of OverType instances\r\n */\r\n static init(target, options = {}) {\r\n return new OverType(target, options);\r\n }\r\n\r\n /**\r\n * Initialize editors with options from data-ot-* attributes\r\n * @param {string} selector - CSS selector for target elements\r\n * @param {Object} defaults - Default options (data attrs override these)\r\n * @returns {Array} Array of OverType instances\r\n * @example\r\n * // HTML:
    \r\n * OverType.initFromData('.editor', { fontSize: '14px' });\r\n */\r\n static initFromData(selector, defaults = {}) {\r\n const elements = document.querySelectorAll(selector);\r\n return Array.from(elements).map(el => {\r\n const options = { ...defaults };\r\n\r\n // Parse data-ot-* attributes (kebab-case to camelCase)\r\n for (const attr of el.attributes) {\r\n if (attr.name.startsWith('data-ot-')) {\r\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\r\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\r\n options[key] = OverType._parseDataValue(attr.value);\r\n }\r\n }\r\n\r\n return new OverType(el, options);\r\n });\r\n }\r\n\r\n /**\r\n * Parse a data attribute value to the appropriate type\r\n * @private\r\n */\r\n static _parseDataValue(value) {\r\n if (value === 'true') return true;\r\n if (value === 'false') return false;\r\n if (value === 'null') return null;\r\n if (value !== '' && !isNaN(Number(value))) return Number(value);\r\n return value;\r\n }\r\n\r\n /**\r\n * Get instance from element\r\n * @param {Element} element - DOM element\r\n * @returns {OverType|null} OverType instance or null\r\n */\r\n static getInstance(element) {\r\n return element.overTypeInstance || OverType.instances.get(element) || null;\r\n }\r\n\r\n /**\r\n * Destroy all instances\r\n */\r\n static destroyAll() {\r\n const elements = document.querySelectorAll('[data-overtype-instance]');\r\n elements.forEach(element => {\r\n const instance = OverType.getInstance(element);\r\n if (instance) {\r\n instance.destroy();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Inject styles into the document\r\n * @param {boolean} force - Force re-injection\r\n */\r\n static injectStyles(force = false) {\r\n if (OverType.stylesInjected && !force) return;\r\n\r\n // Remove any existing OverType styles\r\n const existing = document.querySelector('style.overtype-styles');\r\n if (existing) {\r\n existing.remove();\r\n }\r\n\r\n // Generate and inject new styles with current theme\r\n const theme = OverType.currentTheme || solar;\r\n const styles = generateStyles({ theme });\r\n const styleEl = document.createElement('style');\r\n styleEl.className = 'overtype-styles';\r\n styleEl.textContent = styles;\r\n document.head.appendChild(styleEl);\r\n\r\n OverType.stylesInjected = true;\r\n }\r\n \r\n /**\r\n * Set global theme for all OverType instances\r\n * @param {string|Object} theme - Theme name or custom theme object\r\n * @param {Object} customColors - Optional color overrides\r\n */\r\n static setTheme(theme, customColors = null) {\r\n // Clean up existing auto theme listener\r\n OverType._cleanupGlobalAutoThemeListener();\r\n\r\n // Handle auto theme at global level\r\n if (theme === 'auto') {\r\n OverType._setupGlobalAutoThemeListener();\r\n // Apply the initial resolved theme\r\n const resolvedTheme = resolveAutoTheme('auto');\r\n OverType._applyGlobalResolvedTheme(resolvedTheme, customColors);\r\n } else {\r\n // Process theme\r\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\r\n\r\n // Apply custom colors if provided\r\n if (customColors) {\r\n themeObj = mergeTheme(themeObj, customColors);\r\n }\r\n\r\n // Store as current theme\r\n OverType.currentTheme = themeObj;\r\n\r\n // Re-inject styles with new theme\r\n OverType.injectStyles(true);\r\n\r\n // Update all existing instances - update container theme attribute\r\n document.querySelectorAll('.overtype-container').forEach(container => {\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n if (themeName) {\r\n container.setAttribute('data-theme', themeName);\r\n }\r\n });\r\n\r\n // Also handle any old-style wrappers without containers\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n if (!wrapper.closest('.overtype-container')) {\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n if (themeName) {\r\n wrapper.setAttribute('data-theme', themeName);\r\n }\r\n }\r\n\r\n // Trigger preview update for the instance\r\n const instance = wrapper._instance;\r\n if (instance) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components (shadow DOM instances)\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n // Set the theme attribute to update the theme name\r\n if (themeName && typeof webComponent.setAttribute === 'function') {\r\n webComponent.setAttribute('theme', themeName);\r\n }\r\n // Also call refreshTheme() to handle cases where the theme name stays the same\r\n // but the theme object's properties have changed\r\n if (typeof webComponent.refreshTheme === 'function') {\r\n webComponent.refreshTheme();\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Apply a resolved theme globally (used by auto theme)\r\n * @private\r\n * @param {string} themeName - Resolved theme name\r\n * @param {Object} customColors - Optional color overrides\r\n */\r\n static _applyGlobalResolvedTheme(themeName, customColors = null) {\r\n let themeObj = getTheme(themeName);\r\n\r\n // Apply custom colors if provided\r\n if (customColors) {\r\n themeObj = mergeTheme(themeObj, customColors);\r\n }\r\n\r\n // Store as current theme\r\n OverType.currentTheme = themeObj;\r\n\r\n // Re-inject styles with new theme\r\n OverType.injectStyles(true);\r\n\r\n // Update all containers with resolved theme, but keep 'auto' for tracking\r\n document.querySelectorAll('.overtype-container').forEach(container => {\r\n container.setAttribute('data-theme', 'auto');\r\n container.setAttribute('data-resolved-theme', themeName);\r\n });\r\n\r\n // Also handle any old-style wrappers without containers\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n if (!wrapper.closest('.overtype-container')) {\r\n wrapper.setAttribute('data-theme', 'auto');\r\n wrapper.setAttribute('data-resolved-theme', themeName);\r\n }\r\n\r\n // Trigger preview update for the instance\r\n const instance = wrapper._instance;\r\n if (instance) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.setAttribute === 'function') {\r\n webComponent.setAttribute('theme', 'auto');\r\n webComponent.setAttribute('data-resolved-theme', themeName);\r\n }\r\n if (typeof webComponent.refreshTheme === 'function') {\r\n webComponent.refreshTheme();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Setup global auto theme listener\r\n * @private\r\n */\r\n static _setupGlobalAutoThemeListener() {\r\n if (!window.matchMedia) return;\r\n\r\n OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n OverType.autoThemeListener = (event) => {\r\n const resolvedTheme = event.matches ? 'cave' : 'solar';\r\n OverType._applyGlobalResolvedTheme(resolvedTheme);\r\n };\r\n\r\n // Use addEventListener if available (modern browsers)\r\n if (OverType.autoThemeMediaQuery.addEventListener) {\r\n OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener);\r\n } else if (OverType.autoThemeMediaQuery.addListener) {\r\n // Fallback for older browsers\r\n OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener);\r\n }\r\n }\r\n\r\n /**\r\n * Clean up global auto theme listener\r\n * @private\r\n */\r\n static _cleanupGlobalAutoThemeListener() {\r\n if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) {\r\n if (OverType.autoThemeMediaQuery.removeEventListener) {\r\n OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener);\r\n } else if (OverType.autoThemeMediaQuery.removeListener) {\r\n // Fallback for older browsers\r\n OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener);\r\n }\r\n OverType.autoThemeMediaQuery = null;\r\n OverType.autoThemeListener = null;\r\n }\r\n }\r\n\r\n /**\r\n * Set global code highlighter for all OverType instances\r\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n */\r\n static setCodeHighlighter(highlighter) {\r\n MarkdownParser.setCodeHighlighter(highlighter);\r\n\r\n // Update all existing instances in light DOM\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n const instance = wrapper._instance;\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components (shadow DOM instances)\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.getEditor === 'function') {\r\n const instance = webComponent.getEditor();\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Set custom syntax processor for extending markdown parsing\r\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\r\n * @example\r\n * OverType.setCustomSyntax((html) => {\r\n * // Highlight footnote references [^1]\r\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\r\n * });\r\n */\r\n static setCustomSyntax(processor) {\r\n MarkdownParser.setCustomSyntax(processor);\r\n\r\n // Update all existing instances\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n const instance = wrapper._instance;\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.getEditor === 'function') {\r\n const instance = webComponent.getEditor();\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Initialize global event listeners\r\n */\r\n static initGlobalListeners() {\r\n if (OverType.globalListenersInitialized) return;\r\n\r\n // Input event\r\n document.addEventListener('input', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleInput(e);\r\n }\r\n });\r\n\r\n // Keydown event\r\n document.addEventListener('keydown', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleKeydown(e);\r\n }\r\n });\r\n\r\n // Scroll event\r\n document.addEventListener('scroll', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleScroll(e);\r\n }\r\n }, true);\r\n\r\n // Selection change event\r\n document.addEventListener('selectionchange', (e) => {\r\n const activeElement = document.activeElement;\r\n if (activeElement && activeElement.classList.contains('overtype-input')) {\r\n const wrapper = activeElement.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) {\r\n // Update stats bar for cursor position\r\n if (instance.options.showStats && instance.statsBar) {\r\n instance._updateStats();\r\n }\r\n // Debounce updates\r\n clearTimeout(instance._selectionTimeout);\r\n instance._selectionTimeout = setTimeout(() => {\r\n instance.updatePreview();\r\n }, 50);\r\n }\r\n }\r\n });\r\n\r\n OverType.globalListenersInitialized = true;\r\n }\r\n}\r\n\r\n// Export classes for advanced usage\r\nOverType.MarkdownParser = MarkdownParser;\r\nOverType.ShortcutsManager = ShortcutsManager;\r\n\r\n// Export theme utilities\r\nOverType.themes = { solar, cave: getTheme('cave') };\r\nOverType.getTheme = getTheme;\r\n\r\n// Set default theme\r\nOverType.currentTheme = solar;\r\n\r\n// Export for module systems\r\nexport default OverType;\r\nexport { OverType };\r\n\r\n// Export toolbar buttons for custom toolbar configurations\r\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\r\n"], + "mappings": ";;;;;;;;;;;;;;;AAQO,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA,EAa1B,OAAO,iBAAiB;AACtB,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,aAAa;AACrC,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,gBAAgB,WAAW;AAChC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,MAAM;AAC7B,QAAI,KAAK,cAAc;AACrB,aAAO,KAAK,aAAa,IAAI;AAAA,IAC/B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WAAW,MAAM;AACtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,WAAO,KAAK,QAAQ,YAAY,OAAK,IAAI,CAAC,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,oBAAoB,MAAM,cAAc;AAC7C,UAAM,gBAAgB,aAAa,MAAM,QAAQ,EAAE,CAAC;AACpD,UAAM,cAAc,cAAc,QAAQ,MAAM,QAAQ;AACxD,WAAO,KAAK,QAAQ,QAAQ,WAAW;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,MAAM;AACvB,WAAO,KAAK,QAAQ,oBAAoB,CAAC,OAAO,QAAQ,YAAY;AAClE,YAAM,QAAQ,OAAO;AACrB,aAAO,KAAK,KAAK,gCAAgC,MAAM,WAAW,OAAO,MAAM,KAAK;AAAA,IACtF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,oBAAoB,MAAM;AAC/B,QAAI,KAAK,MAAM,wBAAwB,GAAG;AACxC,aAAO,gCAAgC,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAC3B,WAAO,KAAK,QAAQ,eAAe,CAAC,OAAO,YAAY;AACrD,aAAO,oEAAoE,OAAO;AAAA,IACpF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAC3B,WAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,aAAO,GAAG,MAAM,uDAAuD,MAAM,WAAW,OAAO;AAAA,IACjG,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,cAAc,MAAM,gBAAgB,OAAO;AAChD,WAAO,KAAK,QAAQ,yCAAyC,CAAC,OAAO,QAAQ,SAAS,YAAY;AAChG,UAAI,eAAe;AAEjB,cAAM,YAAY,QAAQ,YAAY,MAAM;AAC5C,eAAO,GAAG,MAAM,gDAAgD,YAAY,YAAY,EAAE,KAAK,OAAO;AAAA,MACxG,OAAO;AAEL,eAAO,GAAG,MAAM,wDAAwD,OAAO,YAAY,OAAO;AAAA,MACpG;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,MAAM;AAC7B,WAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,aAAO,GAAG,MAAM,wDAAwD,MAAM,WAAW,OAAO;AAAA,IAClG,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,eAAe,MAAM;AAE1B,UAAM,iBAAiB;AACvB,QAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,aAAO,iCAAiC,IAAI;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAAM;AACrB,WAAO,KAAK,QAAQ,kBAAkB,+FAA+F;AACrI,WAAO,KAAK,QAAQ,cAAc,+FAA+F;AACjI,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,YAAY,MAAM;AAGvB,WAAO,KAAK,QAAQ,WAAC,gDAAuC,GAAC,GAAE,qFAAqF;AAIpJ,WAAO,KAAK,QAAQ,WAAC,8CAAyC,GAAC,GAAE,qFAAqF;AAEtJ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,mBAAmB,MAAM;AAE9B,WAAO,KAAK,QAAQ,WAAC,mCAAgC,GAAC,GAAE,yFAAyF;AAEjJ,WAAO,KAAK,QAAQ,WAAC,iCAA8B,GAAC,GAAE,uFAAuF;AAC7I,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAS3B,WAAO,KAAK,QAAQ,WAAC,6CAAwC,GAAC,GAAE,2FAA2F;AAAA,EAC7J;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,KAAK;AAEtB,UAAM,UAAU,IAAI,KAAK;AACzB,UAAM,QAAQ,QAAQ,YAAY;AAGlC,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,kBAAkB,cAAc,KAAK,cAAY,MAAM,WAAW,QAAQ,CAAC;AAGjF,UAAM,aAAa,QAAQ,WAAW,GAAG,KACvB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACrB,CAAC,QAAQ,SAAS,GAAG,KAAK,CAAC,QAAQ,SAAS,IAAI;AAGnE,QAAI,mBAAmB,YAAY;AACjC,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WAAW,MAAM;AACtB,WAAO,KAAK,QAAQ,uBAAuB,CAAC,OAAO,MAAM,QAAQ;AAC/D,YAAM,aAAa,UAAU,KAAK,WAAW;AAE7C,YAAM,UAAU,KAAK,YAAY,GAAG;AAEpC,aAAO,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,IAAI,0CAA0C,GAAG;AAAA,IACzJ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,8BAA8B,MAAM;AACzC,UAAM,cAAc,oBAAI,IAAI;AAC5B,QAAI,mBAAmB;AACvB,QAAI,gBAAgB;AAGpB,UAAM,mBAAmB,CAAC;AAG1B,UAAM,YAAY;AAClB,QAAI;AACJ,YAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAIlD,YAAM,aAAa,UAAU,QAAQ,UAAU,CAAC,EAAE,QAAQ,IAAI;AAC9D,YAAM,WAAW,aAAa;AAC9B,YAAM,SAAS,WAAW,UAAU,CAAC,EAAE;AACvC,uBAAiB,KAAK,EAAE,OAAO,UAAU,KAAK,OAAO,CAAC;AAAA,IACxD;AAGA,UAAM,YAAY,WAAC,6CAAwC,GAAC;AAC5D,QAAI;AACJ,UAAM,cAAc,CAAC;AAErB,YAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAClD,YAAM,YAAY,UAAU;AAC5B,YAAM,UAAU,UAAU,QAAQ,UAAU,CAAC,EAAE;AAG/C,YAAM,oBAAoB,iBAAiB;AAAA,QAAK,YAC9C,aAAa,OAAO,SAAS,WAAW,OAAO;AAAA,MACjD;AAEA,UAAI,CAAC,mBAAmB;AACtB,oBAAY,KAAK;AAAA,UACf,OAAO,UAAU,CAAC;AAAA,UAClB,OAAO,UAAU;AAAA,UACjB,WAAW,UAAU,CAAC;AAAA,UACtB,SAAS,UAAU,CAAC;AAAA,UACpB,YAAY,UAAU,CAAC;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF;AAGA,gBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC5C,gBAAY,QAAQ,cAAY;AAC9B,YAAM,cAAc,SAAS,kBAAkB;AAC/C,kBAAY,IAAI,aAAa;AAAA,QAC3B,MAAM;AAAA,QACN,UAAU,SAAS;AAAA,QACnB,WAAW,SAAS;AAAA,QACpB,SAAS,SAAS;AAAA,QAClB,YAAY,SAAS;AAAA,MACvB,CAAC;AACD,sBAAgB,cAAc,UAAU,GAAG,SAAS,KAAK,IAC1C,cACA,cAAc,UAAU,SAAS,QAAQ,SAAS,MAAM,MAAM;AAAA,IAC/E,CAAC;AAGD,oBAAgB,cAAc,QAAQ,4BAA4B,CAAC,OAAO,UAAU,QAAQ;AAC1F,YAAM,cAAc,SAAS,kBAAkB;AAC/C,kBAAY,IAAI,aAAa;AAAA,QAC3B,MAAM;AAAA,QACN,UAAU;AAAA,QACV;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAED,WAAO,EAAE,eAAe,YAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,+BAA+B,MAAM,aAAa;AAEvD,UAAM,eAAe,MAAM,KAAK,YAAY,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACjE,YAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,YAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,iBAAa,QAAQ,iBAAe;AAClC,YAAM,YAAY,YAAY,IAAI,WAAW;AAC7C,UAAI;AAEJ,UAAI,UAAU,SAAS,QAAQ;AAE7B,sBAAc,qCAAqC,UAAU,SAAS,UAAU,UAAU,OAAO,+BAA+B,UAAU,UAAU;AAAA,MACtJ,WAAW,UAAU,SAAS,QAAQ;AAEpC,YAAI,oBAAoB,UAAU;AAIlC,oBAAY,QAAQ,CAAC,gBAAgB,qBAAqB;AACxD,cAAI,kBAAkB,SAAS,gBAAgB,GAAG;AAChD,gBAAI,eAAe,SAAS,QAAQ;AAClC,oBAAM,WAAW,qCAAqC,eAAe,SAAS,UAAU,eAAe,OAAO,+BAA+B,eAAe,UAAU;AACtK,kCAAoB,kBAAkB,QAAQ,kBAAkB,QAAQ;AAAA,YAC1E;AAAA,UACF;AAAA,QACF,CAAC;AAGD,4BAAoB,KAAK,mBAAmB,iBAAiB;AAC7D,4BAAoB,KAAK,UAAU,iBAAiB;AACpD,4BAAoB,KAAK,YAAY,iBAAiB;AAItD,cAAM,aAAa,UAAU,KAAK,WAAW;AAC7C,cAAM,UAAU,KAAK,YAAY,UAAU,GAAG;AAC9C,sBAAc,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,iBAAiB,0CAA0C,UAAU,GAAG;AAAA,MACvL;AAEA,aAAO,KAAK,QAAQ,aAAa,WAAW;AAAA,IAC9C,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,oBAAoB,MAAM;AAE/B,UAAM,EAAE,eAAe,YAAY,IAAI,KAAK,8BAA8B,IAAI;AAG9E,QAAI,OAAO;AACX,WAAO,KAAK,mBAAmB,IAAI;AACnC,WAAO,KAAK,UAAU,IAAI;AAC1B,WAAO,KAAK,YAAY,IAAI;AAG5B,WAAO,KAAK,+BAA+B,MAAM,WAAW;AAE5D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAAM,gBAAgB,OAAO;AAC5C,QAAI,OAAO,KAAK,WAAW,IAAI;AAG/B,WAAO,KAAK,oBAAoB,MAAM,IAAI;AAG1C,UAAM,iBAAiB,KAAK,oBAAoB,IAAI;AACpD,QAAI;AAAgB,aAAO;AAE3B,UAAM,YAAY,KAAK,eAAe,IAAI;AAC1C,QAAI;AAAW,aAAO;AAGtB,WAAO,KAAK,YAAY,IAAI;AAC5B,WAAO,KAAK,gBAAgB,IAAI;AAChC,WAAO,KAAK,cAAc,MAAM,aAAa;AAC7C,WAAO,KAAK,gBAAgB,IAAI;AAChC,WAAO,KAAK,kBAAkB,IAAI;AAGlC,WAAO,KAAK,oBAAoB,IAAI;AAGpC,QAAI,KAAK,KAAK,MAAM,IAAI;AAGtB,aAAO;AAAA,IACT;AAEA,WAAO,QAAQ,IAAI;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,MAAM,MAAM,aAAa,IAAI,oBAAoB,OAAO,qBAAqB,gBAAgB,OAAO;AAEzG,SAAK,eAAe;AAEpB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,cAAc;AAElB,UAAM,cAAc,MAAM,IAAI,CAAC,MAAM,UAAU;AAE7C,UAAI,qBAAqB,UAAU,YAAY;AAC7C,cAAM,UAAU,KAAK,WAAW,IAAI,KAAK;AACzC,eAAO,yBAAyB,OAAO;AAAA,MACzC;AAGA,YAAM,iBAAiB;AACvB,UAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,sBAAc,CAAC;AAEf,eAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,MACnE;AAGA,UAAI,aAAa;AACf,cAAM,UAAU,KAAK,WAAW,IAAI;AACpC,cAAM,WAAW,KAAK,oBAAoB,SAAS,IAAI;AACvD,eAAO,QAAQ,YAAY,QAAQ;AAAA,MACrC;AAGA,aAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,IACnE,CAAC;AAGD,UAAM,OAAO,YAAY,KAAK,EAAE;AAGhC,WAAO,KAAK,gBAAgB,MAAM,mBAAmB;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,gBAAgB,MAAM,qBAAqB;AAEhD,QAAI,OAAO,aAAa,eAAe,CAAC,UAAU;AAEhD,aAAO,KAAK,sBAAsB,MAAM,mBAAmB;AAAA,IAC7D;AAGA,UAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,cAAU,YAAY;AAEtB,QAAI,cAAc;AAClB,QAAI,WAAW;AACf,QAAI,mBAAmB;AACvB,QAAI,cAAc;AAGlB,UAAM,WAAW,MAAM,KAAK,UAAU,QAAQ;AAE9C,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,QAAQ,SAAS,CAAC;AAGxB,UAAI,CAAC,MAAM;AAAY;AAGvB,YAAM,YAAY,MAAM,cAAc,aAAa;AACnD,UAAI,WAAW;AACb,cAAM,YAAY,UAAU;AAC5B,YAAI,UAAU,WAAW,KAAK,GAAG;AAC/B,cAAI,CAAC,aAAa;AAEhB,0BAAc;AAGd,+BAAmB,SAAS,cAAc,KAAK;AAC/C,kBAAM,cAAc,SAAS,cAAc,MAAM;AACjD,6BAAiB,YAAY,WAAW;AACxC,6BAAiB,YAAY;AAG7B,kBAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,gBAAI,MAAM;AACR,0BAAY,YAAY,YAAY,IAAI;AAAA,YAC1C;AAGA,sBAAU,aAAa,kBAAkB,MAAM,WAAW;AAG1D,6BAAiB,eAAe;AAChC,6BAAiB,YAAY;AAC7B,6BAAiB,eAAe;AAChC;AAAA,UACF,OAAO;AAGL,kBAAM,cAAc,uBAAuB,KAAK;AAChD,gBAAI,oBAAoB,eAAe,iBAAiB,cAAc;AACpE,kBAAI;AACF,sBAAM,SAAS;AAAA,kBACb,iBAAiB;AAAA,kBACjB,iBAAiB,aAAa;AAAA,gBAChC;AAGA,oBAAI,UAAU,OAAO,OAAO,SAAS,YAAY;AAC/C,0BAAQ,KAAK,kOAAkO;AAAA,gBAEjP,OAAO;AAGL,sBAAI,UAAU,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AACzD,qCAAiB,aAAa,YAAY;AAAA,kBAC5C;AAAA,gBAEF;AAAA,cACF,SAAS,OAAO;AACd,wBAAQ,KAAK,6BAA6B,KAAK;AAAA,cAEjD;AAAA,YACF;AAEA,0BAAc;AACd,+BAAmB;AACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,eAAe,oBAAoB,MAAM,YAAY,SAAS,CAAC,MAAM,cAAc,aAAa,GAAG;AACrG,cAAM,cAAc,iBAAiB,gBAAgB,iBAAiB,cAAc,MAAM;AAE1F,YAAI,iBAAiB,aAAa,SAAS,GAAG;AAC5C,2BAAiB,gBAAgB;AAAA,QACnC;AAEA,cAAM,WAAW,MAAM,YAAY,QAAQ,WAAW,GAAG;AACzD,yBAAiB,gBAAgB;AAGjC,YAAI,YAAY,YAAY,SAAS,GAAG;AACtC,sBAAY,eAAe;AAAA,QAC7B;AACA,oBAAY,eAAe;AAC3B,cAAM,OAAO;AACb;AAAA,MACF;AAGA,UAAI,WAAW;AACf,UAAI,MAAM,YAAY,OAAO;AAE3B,mBAAW,MAAM,cAAc,IAAI;AAAA,MACrC;AAEA,UAAI,UAAU;AACZ,cAAM,WAAW,SAAS,UAAU,SAAS,aAAa;AAC1D,cAAM,YAAY,SAAS,UAAU,SAAS,cAAc;AAE5D,YAAI,CAAC,YAAY,CAAC,WAAW;AAC3B,wBAAc;AACd,qBAAW;AACX;AAAA,QACF;AAEA,cAAM,UAAU,WAAW,OAAO;AAGlC,YAAI,CAAC,eAAe,aAAa,SAAS;AACxC,wBAAc,SAAS,cAAc,OAAO;AAC5C,oBAAU,aAAa,aAAa,KAAK;AACzC,qBAAW;AAAA,QACb;AAGA,cAAM,mBAAmB,CAAC;AAC1B,mBAAW,QAAQ,MAAM,YAAY;AACnC,cAAI,KAAK,aAAa,KAAK,KAAK,YAAY,MAAM,WAAW,GAAG;AAE9D,6BAAiB,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,UAC5C,WAAW,SAAS,UAAU;AAC5B;AAAA,UACF;AAAA,QACF;AAGA,yBAAiB,QAAQ,UAAQ;AAC/B,mBAAS,aAAa,MAAM,SAAS,UAAU;AAAA,QACjD,CAAC;AAGD,oBAAY,YAAY,QAAQ;AAGhC,cAAM,OAAO;AAAA,MACf,OAAO;AAEL,sBAAc;AACd,mBAAW;AAAA,MACb;AAAA,IACF;AAEA,WAAO,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,sBAAsB,MAAM,qBAAqB;AACtD,QAAI,YAAY;AAGhB,gBAAY,UAAU,QAAQ,wEAAwE,CAAC,UAAU;AAC/G,YAAM,OAAO,MAAM,MAAM,4DAA4D,KAAK,CAAC;AAC3F,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,gBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,gBAAM,gBAAgB,IAAI,MAAM,mCAAmC;AAEnE,cAAI,eAAe,eAAe;AAChC,kBAAM,cAAc,YAAY,CAAC;AACjC,kBAAM,WAAW,cAAc,CAAC;AAEhC,mBAAO,SAAS,QAAQ,4BAA4B,2BAA2B,WAAW,EAAE;AAAA,UAC9F;AACA,iBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,QAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,MACnC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,gBAAY,UAAU,QAAQ,yEAAyE,CAAC,UAAU;AAChH,YAAM,OAAO,MAAM,MAAM,6DAA6D,KAAK,CAAC;AAC5F,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,gBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,gBAAM,gBAAgB,IAAI,MAAM,oCAAoC;AAEpE,cAAI,eAAe,eAAe;AAChC,kBAAM,cAAc,YAAY,CAAC;AACjC,kBAAM,WAAW,cAAc,CAAC;AAEhC,mBAAO,SAAS,QAAQ,6BAA6B,4BAA4B,WAAW,EAAE;AAAA,UAChG;AACA,iBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,QAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,MACnC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,UAAM,iBAAiB;AACvB,gBAAY,UAAU,QAAQ,gBAAgB,CAAC,OAAO,WAAW,SAAS,eAAe;AAEvF,YAAM,QAAQ,QAAQ,MAAM,qBAAqB,KAAK,CAAC;AACvD,YAAM,cAAc,MAAM,IAAI,UAAQ;AAEpC,cAAM,OAAO,KAAK,QAAQ,sBAAsB,IAAI,EACjD,QAAQ,WAAW,GAAG;AACzB,eAAO;AAAA,MACT,CAAC,EAAE,KAAK,IAAI;AAGZ,YAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,YAAM,YAAY,OAAO,oBAAoB,IAAI,MAAM;AAGvD,UAAI,qBAAqB;AAEzB,YAAM,cAAc,uBAAuB,KAAK;AAChD,UAAI,aAAa;AACf,YAAI;AAIF,gBAAM,cAAc,YACjB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,UAAU,GAAG;AAExB,gBAAMA,UAAS,YAAY,aAAa,IAAI;AAI5C,cAAIA,WAAU,OAAOA,QAAO,SAAS,YAAY;AAC/C,oBAAQ,KAAK,4HAA4H;AAAA,UAE3I,OAAO;AAEL,gBAAIA,WAAU,OAAOA,YAAW,YAAYA,QAAO,KAAK,GAAG;AACzD,mCAAqBA;AAAA,YACvB;AAAA,UAEF;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,KAAK,6BAA6B,KAAK;AAAA,QAEjD;AAAA,MACF;AAGA,UAAI,SAAS,iCAAiC,SAAS;AAEvD,gBAAU,gCAAgC,SAAS,IAAI,kBAAkB;AACzE,gBAAU,iCAAiC,UAAU;AAErD,aAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,eAAe,MAAM,gBAAgB;AAE1C,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,aAAa;AACjB,QAAI,YAAY;AAChB,QAAI,YAAY;AAEhB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,aAAa,MAAM,CAAC,EAAE;AAC5B,UAAI,aAAa,cAAc,gBAAgB;AAC7C,oBAAY;AACZ,oBAAY;AACZ;AAAA,MACF;AACA,oBAAc,aAAa;AAAA,IAC7B;AAEA,UAAM,cAAc,MAAM,SAAS;AACnC,UAAM,UAAU,YAAY,YAAY;AAGxC,UAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,cAAc,CAAC;AAAA,QACvB,QAAQ;AAAA,QACR,SAAS,cAAc,CAAC,MAAM;AAAA,QAC9B,SAAS,cAAc,CAAC;AAAA,QACxB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,MAChF;AAAA,IACF;AAGA,UAAM,cAAc,YAAY,MAAM,KAAK,cAAc,MAAM;AAC/D,QAAI,aAAa;AACf,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,YAAY,CAAC;AAAA,QACrB,QAAQ,YAAY,CAAC;AAAA,QACrB,SAAS,YAAY,CAAC;AAAA,QACtB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,YAAY,CAAC,EAAE,SAAS,YAAY,CAAC,EAAE,SAAS;AAAA;AAAA,MAC5E;AAAA,IACF;AAGA,UAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,cAAc,CAAC;AAAA,QACvB,QAAQ,SAAS,cAAc,CAAC,CAAC;AAAA,QACjC,SAAS,cAAc,CAAC;AAAA,QACxB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,MAChF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,SAAS;AAChC,YAAQ,QAAQ,UAAU;AAAA,MACxB,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,MAAM;AAAA,MAC3C,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,SAAS,CAAC;AAAA,MAC/C,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM;AAAA,MAC1B;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,cAAc,MAAM;AACzB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,kBAAkB,oBAAI,IAAI;AAChC,QAAI,SAAS;AAEb,UAAM,SAAS,MAAM,IAAI,UAAQ;AAC/B,YAAM,QAAQ,KAAK,MAAM,KAAK,cAAc,QAAQ;AAEpD,UAAI,OAAO;AACT,cAAM,SAAS,MAAM,CAAC;AACtB,cAAM,cAAc,OAAO;AAC3B,cAAM,UAAU,MAAM,CAAC;AAGvB,YAAI,CAAC,QAAQ;AACX,0BAAgB,MAAM;AAAA,QACxB;AAGA,cAAM,iBAAiB,gBAAgB,IAAI,WAAW,KAAK,KAAK;AAChE,wBAAgB,IAAI,aAAa,aAAa;AAG9C,mBAAW,CAAC,KAAK,KAAK,iBAAiB;AACrC,cAAI,QAAQ,aAAa;AACvB,4BAAgB,OAAO,KAAK;AAAA,UAC9B;AAAA,QACF;AAEA,iBAAS;AACT,eAAO,GAAG,MAAM,GAAG,aAAa,KAAK,OAAO;AAAA,MAC9C,OAAO;AAEL,YAAI,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,MAAM,KAAK,GAAG;AAE5C,mBAAS;AACT,0BAAgB,MAAM;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,OAAO,KAAK,IAAI;AAAA,EACzB;AACF;AAAA;AA18BE,cAFW,gBAEJ,aAAY;AAAA;AAGnB,cALW,gBAKJ,mBAAkB;AAAA;AAGzB,cARW,gBAQJ,gBAAe;AAAA;AAAA;AAAA;AAsyBtB,cA9yBW,gBA8yBJ,iBAAgB;AAAA,EACrB,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AACZ;;;AClzBK,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAY,QAAQ;AAClB,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,OAAO;AACnB,UAAM,QAAQ,UAAU,SAAS,YAAY,EAAE,SAAS,KAAK;AAC7D,UAAM,SAAS,QAAQ,MAAM,UAAU,MAAM;AAE7C,QAAI,CAAC;AAAQ,aAAO;AAEpB,QAAI,WAAW;AAEf,YAAQ,MAAM,IAAI,YAAY,GAAG;AAAA,MAC/B,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,MAAM;AAAU,qBAAW;AAC/B;AAAA,MACF,KAAK;AACH,YAAI,MAAM;AAAU,qBAAW;AAC/B;AAAA,IACJ;AAEA,QAAI,UAAU;AACZ,YAAM,eAAe;AACrB,WAAK,OAAO,cAAc,UAAU,KAAK;AACzC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,EAEV;AACF;;;ACnDO,IAAM,QAAQ;AAAA,EACnB,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,MAAM;AAAA;AAAA,IACN,aAAa;AAAA;AAAA,IACb,eAAe;AAAA;AAAA,IACf,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,QAAQ;AAAA;AAAA,IACR,IAAI;AAAA;AAAA,IACJ,KAAK;AAAA;AAAA,IACL,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA;AAAA,IACR,YAAY;AAAA;AAAA,IACZ,IAAI;AAAA;AAAA,IACJ,cAAc;AAAA;AAAA,IACd,QAAQ;AAAA;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,SAAS;AAAA;AAAA,IACT,QAAQ;AAAA;AAAA,IACR,SAAS;AAAA;AAAA,IACT,SAAS;AAAA;AAAA;AAAA,IAET,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,eAAe;AAAA;AAAA,EACjB;AACF;AAKO,IAAM,OAAO;AAAA,EAClB,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,MAAM;AAAA;AAAA,IACN,aAAa;AAAA;AAAA,IACb,eAAe;AAAA;AAAA,IACf,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,QAAQ;AAAA;AAAA,IACR,IAAI;AAAA;AAAA,IACJ,KAAK;AAAA;AAAA,IACL,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA;AAAA,IACR,YAAY;AAAA;AAAA,IACZ,IAAI;AAAA;AAAA,IACJ,cAAc;AAAA;AAAA,IACd,QAAQ;AAAA;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,SAAS;AAAA;AAAA,IACT,QAAQ;AAAA;AAAA,IACR,SAAS;AAAA;AAAA,IACT,SAAS;AAAA;AAAA;AAAA,IAET,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,eAAe;AAAA;AAAA,EACjB;AACF;AAMO,IAAM,OAAO;AAAA,EAClB,MAAM;AAAA;AAAA,EAEN,QAAQ,MAAM;AAAA;AAChB;AAKO,IAAM,SAAS;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,OAAO;AAAA,EACP,MAAM;AACR;AAOO,SAAS,SAAS,OAAO;AAC9B,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AAEzC,WAAO,EAAE,GAAG,UAAU,MAAM,MAAM;AAAA,EACpC;AACA,SAAO;AACT;AAOO,SAAS,iBAAiB,WAAW;AAC1C,MAAI,cAAc,QAAQ;AACxB,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,OAAO,cAAc,OAAO,WAAW,8BAA8B,EAAE;AAC1F,SAAO,aAAa,SAAS;AAC/B;AAgBO,SAAS,eAAe,QAAQ;AACrC,QAAM,OAAO,CAAC;AACd,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAEjD,UAAM,UAAU,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC3D,SAAK,KAAK,KAAK,OAAO,KAAK,KAAK,GAAG;AAAA,EACrC;AACA,SAAO,KAAK,KAAK,IAAI;AACvB;AAQO,SAAS,WAAW,WAAW,eAAe,CAAC,GAAG;AACvD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ;AAAA,MACN,GAAG,UAAU;AAAA,MACb,GAAG;AAAA,IACL;AAAA,EACF;AACF;;;AChKO,SAAS,eAAe,UAAU,CAAC,GAAG;AAC3C,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,aAAa;AAAA;AAAA,IAEb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS,CAAC;AAAA,EACZ,IAAI;AAGJ,QAAM,eAAe,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI;AAAA;AAAA;AAAA;AAAA,UAI9C,OAAO,QAAQ,MAAM,EACpB,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AACpB,UAAM,UAAU,KAAK,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC5D,WAAO,GAAG,OAAO,KAAK,GAAG;AAAA,EAC3B,CAAC,EACA,KAAK,YAAY,CAAC;AAAA;AAAA;AAAA,MAGvB;AAGJ,QAAM,YAAY,SAAS,MAAM,SAAS,eAAe,MAAM,MAAM,IAAI;AAEzE,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAyCD,YAAY;AAAA;AAAA,QAEZ,SAAS,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAyCH,UAAU;AAAA;AAAA,6CAEc,QAAQ;AAAA,iDACJ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCASlB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;;;;;;;;;;;;;AC92BO,IAAM,UAA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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons", "themeName"] } diff --git a/dist/overtype.js b/dist/overtype.js index 6c82ffc..d6124b0 100644 --- a/dist/overtype.js +++ b/dist/overtype.js @@ -1,5 +1,5 @@ /** - * OverType v2.1.0 + * OverType v2.1.1 * A lightweight markdown editor library with perfect WYSIWYG alignment * @license MIT * @author David Miranda @@ -940,9 +940,16 @@ var OverType = (() => { // Even lighter - active button background } }; + var auto = { + name: "auto", + // The auto theme doesn't have its own colors; it uses solar or cave dynamically + colors: solar.colors + // Default to solar colors for initial render + }; var themes = { solar, cave, + auto, // Aliases for backward compatibility light: solar, dark: cave @@ -954,6 +961,13 @@ var OverType = (() => { } return theme; } + function resolveAutoTheme(themeName) { + if (themeName !== "auto") { + return themeName; + } + const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; + return isDarkMode ? "cave" : "solar"; + } function themeToCSSVars(colors) { const vars = []; for (const [key, value] of Object.entries(colors)) { @@ -3385,6 +3399,7 @@ ${blockSuffix}` : suffix; return false; } var _OverType = class _OverType { + // Listener function for auto theme changes /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -3428,6 +3443,8 @@ ${blockSuffix}` : suffix; _init(element, options = {}) { this.element = element; this.instanceTheme = options.theme || null; + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; this.options = this._mergeOptions(options); this.instanceId = ++_OverType.instanceCount; this.initialized = false; @@ -3440,6 +3457,9 @@ ${blockSuffix}` : suffix; } else { this._buildFromScratch(); } + if (this.instanceTheme) { + this.setTheme(this.instanceTheme); + } this.shortcuts = new ShortcutsManager(this); this._rebuildActionsMap(); this.linkTooltip = new LinkTooltip(this); @@ -4079,18 +4099,73 @@ ${blockSuffix}` : suffix; * @returns {this} Returns this for chaining */ setTheme(theme) { + this._cleanupAutoThemeListener(); this.instanceTheme = theme; - const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName) { - this.container.setAttribute("data-theme", themeName); + if (theme === "auto") { + this._setupAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + this._applyResolvedTheme(resolvedTheme); + } else { + const themeObj = typeof theme === "string" ? getTheme(theme) : theme; + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName) { + this.container.setAttribute("data-theme", themeName); + } + if (themeObj && themeObj.colors) { + const cssVars = themeToCSSVars(themeObj.colors); + this.container.style.cssText += cssVars; + } + this.updatePreview(); } + return this; + } + /** + * Apply a resolved theme name (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + */ + _applyResolvedTheme(themeName) { + const themeObj = getTheme(themeName); + this.container.setAttribute("data-theme", "auto"); + this.container.setAttribute("data-resolved-theme", themeName); if (themeObj && themeObj.colors) { const cssVars = themeToCSSVars(themeObj.colors); this.container.style.cssText += cssVars; } this.updatePreview(); - return this; + } + /** + * Setup auto theme listener for instance + * @private + */ + _setupAutoThemeListener() { + if (!window.matchMedia) + return; + this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + this.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + this._applyResolvedTheme(resolvedTheme); + }; + if (this.autoThemeMediaQuery.addEventListener) { + this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.addListener) { + this.autoThemeMediaQuery.addListener(this.autoThemeListener); + } + } + /** + * Clean up auto theme listener for instance + * @private + */ + _cleanupAutoThemeListener() { + if (this.autoThemeMediaQuery && this.autoThemeListener) { + if (this.autoThemeMediaQuery.removeEventListener) { + this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); + } else if (this.autoThemeMediaQuery.removeListener) { + this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + } + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; + } } /** * Set instance-specific code highlighter @@ -4244,6 +4319,7 @@ ${blockSuffix}` : suffix; * Destroy the editor instance */ destroy() { + this._cleanupAutoThemeListener(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4349,40 +4425,117 @@ ${blockSuffix}` : suffix; * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + _OverType._cleanupGlobalAutoThemeListener(); + if (theme === "auto") { + _OverType._setupGlobalAutoThemeListener(); + const resolvedTheme = resolveAutoTheme("auto"); + _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + } else { + let themeObj = typeof theme === "string" ? getTheme(theme) : theme; + if (customColors) { + themeObj = mergeTheme(themeObj, customColors); + } + _OverType.currentTheme = themeObj; + _OverType.injectStyles(true); + document.querySelectorAll(".overtype-container").forEach((container) => { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + container.setAttribute("data-theme", themeName2); + } + }); + document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { + if (!wrapper.closest(".overtype-container")) { + const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; + if (themeName2) { + wrapper.setAttribute("data-theme", themeName2); + } + } + const instance = wrapper._instance; + if (instance) { + instance.updatePreview(); + } + }); + const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + document.querySelectorAll("overtype-editor").forEach((webComponent) => { + if (themeName && typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", themeName); + } + if (typeof webComponent.refreshTheme === "function") { + webComponent.refreshTheme(); + } + }); + } + } + /** + * Apply a resolved theme globally (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + * @param {Object} customColors - Optional color overrides + */ + static _applyGlobalResolvedTheme(themeName, customColors = null) { + let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } + container.setAttribute("data-theme", "auto"); + container.setAttribute("data-resolved-theme", themeName); }); document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); } const instance = wrapper._instance; if (instance) { instance.updatePreview(); } }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); + if (typeof webComponent.setAttribute === "function") { + webComponent.setAttribute("theme", "auto"); + webComponent.setAttribute("data-resolved-theme", themeName); } if (typeof webComponent.refreshTheme === "function") { webComponent.refreshTheme(); } }); } + /** + * Setup global auto theme listener + * @private + */ + static _setupGlobalAutoThemeListener() { + if (!window.matchMedia) + return; + _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? "cave" : "solar"; + _OverType._applyGlobalResolvedTheme(resolvedTheme); + }; + if (_OverType.autoThemeMediaQuery.addEventListener) { + _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.addListener) { + _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + } + } + /** + * Clean up global auto theme listener + * @private + */ + static _cleanupGlobalAutoThemeListener() { + if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { + if (_OverType.autoThemeMediaQuery.removeEventListener) { + _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); + } else if (_OverType.autoThemeMediaQuery.removeListener) { + _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + } + _OverType.autoThemeMediaQuery = null; + _OverType.autoThemeListener = null; + } + } /** * Set global code highlighter for all OverType instances * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML @@ -4484,6 +4637,9 @@ ${blockSuffix}` : suffix; __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); + __publicField(_OverType, "autoThemeMediaQuery", null); + // Media query for auto theme switching + __publicField(_OverType, "autoThemeListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype.js.map b/dist/overtype.js.map index 3e0eeb9..86e1f97 100644 --- a/dist/overtype.js.map +++ b/dist/overtype.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/overtype.js", "../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js"], - "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Get theme object\n      const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n      const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n      // Update container theme attribute\n      if (themeName) {\n        this.container.setAttribute('data-theme', themeName);\n      }\n\n      // Apply CSS variables to container for instance override\n      if (themeObj && themeObj.colors) {\n        const cssVars = themeToCSSVars(themeObj.colors);\n        this.container.style.cssText += cssVars;\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n\n      return this;\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances - update container theme attribute\n document.querySelectorAll('.overtype-container').forEach(container => {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n container.setAttribute('data-theme', themeName);\n }\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n // Set the theme attribute to update the theme name\n if (themeName && typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', themeName);\n }\n // Also call refreshTheme() to handle cases where the theme name stays the same\n // but the theme object's properties have changed\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], - "mappings": "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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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", + "sourcesContent": ["/**\r\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\r\n * @version 1.0.0\r\n * @license MIT\r\n */\r\n\r\nimport { MarkdownParser } from './parser.js';\r\nimport { ShortcutsManager } from './shortcuts.js';\r\nimport { generateStyles } from './styles.js';\r\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\r\nimport { Toolbar } from './toolbar.js';\r\nimport { LinkTooltip } from './link-tooltip.js';\r\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\r\n\r\n/**\r\n * Build action map from toolbar button configurations\r\n * @param {Array} buttons - Array of button config objects\r\n * @returns {Object} Map of actionId -> action function\r\n */\r\nfunction buildActionsMap(buttons) {\r\n const map = {};\r\n (buttons || []).forEach((btn) => {\r\n if (!btn || btn.name === 'separator') return;\r\n const id = btn.actionId || btn.name;\r\n if (btn.action) {\r\n map[id] = btn.action;\r\n }\r\n });\r\n return map;\r\n}\r\n\r\n/**\r\n * Normalize toolbar buttons for comparison\r\n * @param {Array|null} buttons\r\n * @returns {Array|null}\r\n */\r\nfunction normalizeButtons(buttons) {\r\n const list = buttons || defaultToolbarButtons;\r\n if (!Array.isArray(list)) return null;\r\n return list.map((btn) => ({\r\n name: btn?.name || null,\r\n actionId: btn?.actionId || btn?.name || null,\r\n icon: btn?.icon || null,\r\n title: btn?.title || null\r\n }));\r\n}\r\n\r\n/**\r\n * Determine if toolbar button configuration changed\r\n * @param {Array|null} prevButtons\r\n * @param {Array|null} nextButtons\r\n * @returns {boolean}\r\n */\r\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\r\n const prev = normalizeButtons(prevButtons);\r\n const next = normalizeButtons(nextButtons);\r\n\r\n if (prev === null || next === null) return prev !== next;\r\n if (prev.length !== next.length) return true;\r\n\r\n for (let i = 0; i < prev.length; i++) {\r\n const a = prev[i];\r\n const b = next[i];\r\n if (a.name !== b.name ||\r\n a.actionId !== b.actionId ||\r\n a.icon !== b.icon ||\r\n a.title !== b.title) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * OverType Editor Class\r\n */\r\nclass OverType {\r\n // Static properties\r\n static instances = new WeakMap();\r\n static stylesInjected = false;\r\n static globalListenersInitialized = false;\r\n static instanceCount = 0;\r\n static autoThemeMediaQuery = null; // Media query for auto theme switching\r\n static autoThemeListener = null; // Listener function for auto theme changes\r\n\r\n /**\r\n * Constructor - Always returns an array of instances\r\n * @param {string|Element|NodeList|Array} target - Target element(s)\r\n * @param {Object} options - Configuration options\r\n * @returns {Array} Array of OverType instances\r\n */\r\n constructor(target, options = {}) {\r\n // Convert target to array of elements\r\n let elements;\r\n \r\n if (typeof target === 'string') {\r\n elements = document.querySelectorAll(target);\r\n if (elements.length === 0) {\r\n throw new Error(`No elements found for selector: ${target}`);\r\n }\r\n elements = Array.from(elements);\r\n } else if (target instanceof Element) {\r\n elements = [target];\r\n } else if (target instanceof NodeList) {\r\n elements = Array.from(target);\r\n } else if (Array.isArray(target)) {\r\n elements = target;\r\n } else {\r\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\r\n }\r\n\r\n // Initialize all elements and return array\r\n const instances = elements.map(element => {\r\n // Check for existing instance\r\n if (element.overTypeInstance) {\r\n // Re-init existing instance\r\n element.overTypeInstance.reinit(options);\r\n return element.overTypeInstance;\r\n }\r\n\r\n // Create new instance\r\n const instance = Object.create(OverType.prototype);\r\n instance._init(element, options);\r\n element.overTypeInstance = instance;\r\n OverType.instances.set(element, instance);\r\n return instance;\r\n });\r\n\r\n return instances;\r\n }\r\n\r\n /**\r\n * Internal initialization\r\n * @private\r\n */\r\n _init(element, options = {}) {\r\n this.element = element;\r\n \r\n // Store the original theme option before merging\r\n this.instanceTheme = options.theme || null;\r\n \r\n // Auto theme tracking for instance-level theme\r\n this.autoThemeMediaQuery = null;\r\n this.autoThemeListener = null;\r\n \r\n this.options = this._mergeOptions(options);\r\n this.instanceId = ++OverType.instanceCount;\r\n this.initialized = false;\r\n\r\n // Inject styles if needed\r\n OverType.injectStyles();\r\n\r\n // Initialize global listeners\r\n OverType.initGlobalListeners();\r\n\r\n // Check for existing OverType DOM structure\r\n const container = element.querySelector('.overtype-container');\r\n const wrapper = element.querySelector('.overtype-wrapper');\r\n if (container || wrapper) {\r\n this._recoverFromDOM(container, wrapper);\r\n } else {\r\n this._buildFromScratch();\r\n }\r\n\r\n // Set up instance theme if provided (including auto theme listener)\r\n if (this.instanceTheme) {\r\n this.setTheme(this.instanceTheme);\r\n }\r\n\r\n // Setup shortcuts manager\r\n this.shortcuts = new ShortcutsManager(this);\r\n\r\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\r\n this._rebuildActionsMap();\r\n\r\n // Setup link tooltip\r\n this.linkTooltip = new LinkTooltip(this);\r\n\r\n // Sync scroll positions on initial render\r\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\r\n // Double requestAnimationFrame waits for browser to restore scroll position\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(() => {\r\n this.textarea.scrollTop = this.preview.scrollTop;\r\n this.textarea.scrollLeft = this.preview.scrollLeft;\r\n });\r\n });\r\n\r\n // Mark as initialized\r\n this.initialized = true;\r\n\r\n // Call onChange if provided\r\n if (this.options.onChange) {\r\n this.options.onChange(this.getValue(), this);\r\n }\r\n }\r\n\r\n /**\r\n * Merge user options with defaults\r\n * @private\r\n */\r\n _mergeOptions(options) {\r\n const defaults = {\r\n // Typography\r\n fontSize: '14px',\r\n lineHeight: 1.6,\r\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\r\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\r\n padding: '16px',\r\n \r\n // Mobile styles\r\n mobile: {\r\n fontSize: '16px', // Prevent zoom on iOS\r\n padding: '12px',\r\n lineHeight: 1.5\r\n },\r\n \r\n // Native textarea properties\r\n textareaProps: {},\r\n \r\n // Behavior\r\n autofocus: false,\r\n autoResize: false, // Auto-expand height with content\r\n minHeight: '100px', // Minimum height for autoResize mode\r\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\r\n placeholder: 'Start typing...',\r\n value: '',\r\n \r\n // Callbacks\r\n onChange: null,\r\n onKeydown: null,\r\n \r\n // Features\r\n showActiveLineRaw: false,\r\n showStats: false,\r\n toolbar: false,\r\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\r\n statsFormatter: null,\r\n smartLists: true, // Enable smart list continuation\r\n codeHighlighter: null // Per-instance code highlighter\r\n };\r\n \r\n // Remove theme and colors from options - these are now global\r\n const { theme, colors, ...cleanOptions } = options;\r\n \r\n return {\r\n ...defaults,\r\n ...cleanOptions\r\n };\r\n }\r\n\r\n /**\r\n * Recover from existing DOM structure\r\n * @private\r\n */\r\n _recoverFromDOM(container, wrapper) {\r\n // Handle old structure (wrapper only) or new structure (container + wrapper)\r\n if (container && container.classList.contains('overtype-container')) {\r\n this.container = container;\r\n this.wrapper = container.querySelector('.overtype-wrapper');\r\n } else if (wrapper) {\r\n // Old structure - just wrapper, no container\r\n this.wrapper = wrapper;\r\n // Wrap it in a container for consistency\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-container';\r\n // Use instance theme if provided, otherwise use global theme\r\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\r\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\r\n if (themeName) {\r\n this.container.setAttribute('data-theme', themeName);\r\n }\r\n \r\n // If using instance theme, apply CSS variables to container\r\n if (this.instanceTheme) {\r\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\r\n if (themeObj && themeObj.colors) {\r\n const cssVars = themeToCSSVars(themeObj.colors);\r\n this.container.style.cssText += cssVars;\r\n }\r\n }\r\n wrapper.parentNode.insertBefore(this.container, wrapper);\r\n this.container.appendChild(wrapper);\r\n }\r\n \r\n if (!this.wrapper) {\r\n // No valid structure found\r\n if (container) container.remove();\r\n if (wrapper) wrapper.remove();\r\n this._buildFromScratch();\r\n return;\r\n }\r\n \r\n this.textarea = this.wrapper.querySelector('.overtype-input');\r\n this.preview = this.wrapper.querySelector('.overtype-preview');\r\n\r\n if (!this.textarea || !this.preview) {\r\n // Partial DOM - clear and rebuild\r\n this.container.remove();\r\n this._buildFromScratch();\r\n return;\r\n }\r\n\r\n // Store reference on wrapper\r\n this.wrapper._instance = this;\r\n \r\n // Apply instance-specific styles via CSS custom properties\r\n if (this.options.fontSize) {\r\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\r\n }\r\n if (this.options.lineHeight) {\r\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\r\n }\r\n if (this.options.padding) {\r\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\r\n }\r\n\r\n // Disable autofill, spellcheck, and extensions\r\n this._configureTextarea();\r\n\r\n // Apply any new options\r\n this._applyOptions();\r\n }\r\n\r\n /**\r\n * Build editor from scratch\r\n * @private\r\n */\r\n _buildFromScratch() {\r\n // Extract any existing content\r\n const content = this._extractContent();\r\n\r\n // Clear element\r\n this.element.innerHTML = '';\r\n\r\n // Create DOM structure\r\n this._createDOM();\r\n\r\n // Set initial content\r\n if (content || this.options.value) {\r\n this.setValue(content || this.options.value);\r\n }\r\n\r\n // Apply options\r\n this._applyOptions();\r\n }\r\n\r\n /**\r\n * Extract content from element\r\n * @private\r\n */\r\n _extractContent() {\r\n // Look for existing OverType textarea\r\n const textarea = this.element.querySelector('.overtype-input');\r\n if (textarea) return textarea.value;\r\n\r\n // Use element's text content as fallback\r\n return this.element.textContent || '';\r\n }\r\n\r\n /**\r\n * Create DOM structure\r\n * @private\r\n */\r\n _createDOM() {\r\n // Create container that will hold toolbar and editor\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-container';\r\n \r\n // Set theme on container - use instance theme if provided\r\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\r\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\r\n if (themeName) {\r\n this.container.setAttribute('data-theme', themeName);\r\n }\r\n \r\n // If using instance theme, apply CSS variables to container\r\n if (this.instanceTheme) {\r\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\r\n if (themeObj && themeObj.colors) {\r\n const cssVars = themeToCSSVars(themeObj.colors);\r\n this.container.style.cssText += cssVars;\r\n }\r\n }\r\n \r\n // Create wrapper for editor\r\n this.wrapper = document.createElement('div');\r\n this.wrapper.className = 'overtype-wrapper';\r\n \r\n \r\n // Apply instance-specific styles via CSS custom properties\r\n if (this.options.fontSize) {\r\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\r\n }\r\n if (this.options.lineHeight) {\r\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\r\n }\r\n if (this.options.padding) {\r\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\r\n }\r\n \r\n this.wrapper._instance = this;\r\n\r\n // Create textarea\r\n this.textarea = document.createElement('textarea');\r\n this.textarea.className = 'overtype-input';\r\n this.textarea.placeholder = this.options.placeholder;\r\n this._configureTextarea();\r\n \r\n // Apply any native textarea properties\r\n if (this.options.textareaProps) {\r\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\r\n if (key === 'className' || key === 'class') {\r\n this.textarea.className += ' ' + value;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n Object.assign(this.textarea.style, value);\r\n } else {\r\n this.textarea.setAttribute(key, value);\r\n }\r\n });\r\n }\r\n\r\n // Create preview div\r\n this.preview = document.createElement('div');\r\n this.preview.className = 'overtype-preview';\r\n this.preview.setAttribute('aria-hidden', 'true');\r\n\r\n // Assemble DOM\r\n this.wrapper.appendChild(this.textarea);\r\n this.wrapper.appendChild(this.preview);\r\n \r\n // No need to prevent link clicks - pointer-events handles this\r\n \r\n // Add wrapper to container first\r\n this.container.appendChild(this.wrapper);\r\n \r\n // Add stats bar at the end (bottom) if enabled\r\n if (this.options.showStats) {\r\n this.statsBar = document.createElement('div');\r\n this.statsBar.className = 'overtype-stats';\r\n this.container.appendChild(this.statsBar);\r\n this._updateStats();\r\n }\r\n \r\n // Add container to element\r\n this.element.appendChild(this.container);\r\n \r\n // Setup auto-resize if enabled\r\n if (this.options.autoResize) {\r\n this._setupAutoResize();\r\n } else {\r\n // Ensure auto-resize class is removed if not using auto-resize\r\n this.container.classList.remove('overtype-auto-resize');\r\n }\r\n }\r\n\r\n /**\r\n * Configure textarea attributes\r\n * @private\r\n */\r\n _configureTextarea() {\r\n this.textarea.setAttribute('autocomplete', 'off');\r\n this.textarea.setAttribute('autocorrect', 'off');\r\n this.textarea.setAttribute('autocapitalize', 'off');\r\n this.textarea.setAttribute('spellcheck', 'false');\r\n this.textarea.setAttribute('data-gramm', 'false');\r\n this.textarea.setAttribute('data-gramm_editor', 'false');\r\n this.textarea.setAttribute('data-enable-grammarly', 'false');\r\n }\r\n\r\n /**\r\n * Create and setup toolbar\r\n * @private\r\n */\r\n _createToolbar() {\r\n // Use provided toolbarButtons or default to defaultToolbarButtons\r\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\r\n\r\n this.toolbar = new Toolbar(this, { toolbarButtons });\r\n this.toolbar.create();\r\n\r\n // Store listener references for cleanup\r\n this._toolbarSelectionListener = () => {\r\n if (this.toolbar) {\r\n this.toolbar.updateButtonStates();\r\n }\r\n };\r\n this._toolbarInputListener = () => {\r\n if (this.toolbar) {\r\n this.toolbar.updateButtonStates();\r\n }\r\n };\r\n\r\n // Add listeners\r\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\r\n this.textarea.addEventListener('input', this._toolbarInputListener);\r\n }\r\n\r\n /**\r\n * Cleanup toolbar event listeners\r\n * @private\r\n */\r\n _cleanupToolbarListeners() {\r\n if (this._toolbarSelectionListener) {\r\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\r\n this._toolbarSelectionListener = null;\r\n }\r\n if (this._toolbarInputListener) {\r\n this.textarea.removeEventListener('input', this._toolbarInputListener);\r\n this._toolbarInputListener = null;\r\n }\r\n }\r\n\r\n /**\r\n * Rebuild the action map from current toolbar button configuration\r\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\r\n * @private\r\n */\r\n _rebuildActionsMap() {\r\n // Always start with default actions (shortcuts always work regardless of toolbar config)\r\n this.actionsById = buildActionsMap(defaultToolbarButtons);\r\n\r\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\r\n if (this.options.toolbarButtons) {\r\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\r\n }\r\n }\r\n\r\n /**\r\n * Apply options to the editor\r\n * @private\r\n */\r\n _applyOptions() {\r\n // Apply autofocus\r\n if (this.options.autofocus) {\r\n this.textarea.focus();\r\n }\r\n\r\n // Setup or remove auto-resize\r\n if (this.options.autoResize) {\r\n if (!this.container.classList.contains('overtype-auto-resize')) {\r\n this._setupAutoResize();\r\n }\r\n } else {\r\n // Ensure auto-resize class is removed\r\n this.container.classList.remove('overtype-auto-resize');\r\n }\r\n\r\n // Handle toolbar option changes\r\n if (this.options.toolbar && !this.toolbar) {\r\n // Create toolbar if enabled and doesn't exist\r\n this._createToolbar();\r\n } else if (!this.options.toolbar && this.toolbar) {\r\n // Destroy toolbar if disabled and exists\r\n this._cleanupToolbarListeners();\r\n this.toolbar.destroy();\r\n this.toolbar = null;\r\n }\r\n\r\n // Update preview with initial content\r\n this.updatePreview();\r\n }\r\n\r\n /**\r\n * Update preview with parsed markdown\r\n */\r\n updatePreview() {\r\n const text = this.textarea.value;\r\n const cursorPos = this.textarea.selectionStart;\r\n const activeLine = this._getCurrentLine(text, cursorPos);\r\n\r\n // Detect if we're in preview mode\r\n const isPreviewMode = this.container.dataset.mode === 'preview';\r\n\r\n // Parse markdown\r\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\r\n this.preview.innerHTML = html || 'Start typing...';\r\n \r\n // Apply code block backgrounds\r\n this._applyCodeBlockBackgrounds();\r\n \r\n // Links always have real hrefs now - no need to update them\r\n \r\n // Update stats if enabled\r\n if (this.options.showStats && this.statsBar) {\r\n this._updateStats();\r\n }\r\n \r\n // Trigger onChange callback\r\n if (this.options.onChange && this.initialized) {\r\n this.options.onChange(text, this);\r\n }\r\n }\r\n\r\n /**\r\n * Apply background styling to code blocks\r\n * @private\r\n */\r\n _applyCodeBlockBackgrounds() {\r\n // Find all code fence elements\r\n const codeFences = this.preview.querySelectorAll('.code-fence');\r\n \r\n // Process pairs of code fences\r\n for (let i = 0; i < codeFences.length - 1; i += 2) {\r\n const openFence = codeFences[i];\r\n const closeFence = codeFences[i + 1];\r\n \r\n // Get parent divs\r\n const openParent = openFence.parentElement;\r\n const closeParent = closeFence.parentElement;\r\n \r\n if (!openParent || !closeParent) continue;\r\n \r\n // Make fences display: block\r\n openFence.style.display = 'block';\r\n closeFence.style.display = 'block';\r\n \r\n // Apply class to parent divs\r\n openParent.classList.add('code-block-line');\r\n closeParent.classList.add('code-block-line');\r\n \r\n // With the new structure, there's a
     block between fences, not DIVs\r\n        // We don't need to process anything between the fences anymore\r\n        // The 
     structure already handles the content correctly\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Get current line number from cursor position\r\n     * @private\r\n     */\r\n    _getCurrentLine(text, cursorPos) {\r\n      const lines = text.substring(0, cursorPos).split('\\n');\r\n      return lines.length - 1;\r\n    }\r\n\r\n    /**\r\n     * Handle input events\r\n     * @private\r\n     */\r\n    handleInput(event) {\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Handle keydown events\r\n     * @private\r\n     */\r\n    handleKeydown(event) {\r\n      // Handle Tab key to prevent focus loss and insert spaces\r\n      if (event.key === 'Tab') {\r\n        const start = this.textarea.selectionStart;\r\n        const end = this.textarea.selectionEnd;\r\n        const value = this.textarea.value;\r\n\r\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\r\n        if (event.shiftKey && start === end) {\r\n          return;\r\n        }\r\n\r\n        event.preventDefault();\r\n\r\n        // If there's a selection, indent/outdent based on shift key\r\n        if (start !== end && event.shiftKey) {\r\n          // Outdent: remove 2 spaces from start of each selected line\r\n          const before = value.substring(0, start);\r\n          const selection = value.substring(start, end);\r\n          const after = value.substring(end);\r\n          \r\n          const lines = selection.split('\\n');\r\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\r\n          \r\n          // Try to use execCommand first to preserve undo history\r\n          if (document.execCommand) {\r\n            // Select the text that needs to be replaced\r\n            this.textarea.setSelectionRange(start, end);\r\n            document.execCommand('insertText', false, outdented);\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = before + outdented + after;\r\n            this.textarea.selectionStart = start;\r\n            this.textarea.selectionEnd = start + outdented.length;\r\n          }\r\n        } else if (start !== end) {\r\n          // Indent: add 2 spaces to start of each selected line\r\n          const before = value.substring(0, start);\r\n          const selection = value.substring(start, end);\r\n          const after = value.substring(end);\r\n          \r\n          const lines = selection.split('\\n');\r\n          const indented = lines.map(line => '  ' + line).join('\\n');\r\n          \r\n          // Try to use execCommand first to preserve undo history\r\n          if (document.execCommand) {\r\n            // Select the text that needs to be replaced\r\n            this.textarea.setSelectionRange(start, end);\r\n            document.execCommand('insertText', false, indented);\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = before + indented + after;\r\n            this.textarea.selectionStart = start;\r\n            this.textarea.selectionEnd = start + indented.length;\r\n          }\r\n        } else {\r\n          // No selection: just insert 2 spaces\r\n          // Use execCommand to preserve undo history\r\n          if (document.execCommand) {\r\n            document.execCommand('insertText', false, '  ');\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\r\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\r\n          }\r\n        }\r\n        \r\n        // Trigger input event to update preview\r\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n        return;\r\n      }\r\n      \r\n      // Handle Enter key for smart list continuation\r\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\r\n        if (this.handleSmartListContinuation()) {\r\n          event.preventDefault();\r\n          return;\r\n        }\r\n      }\r\n      \r\n      // Let shortcuts manager handle other keys\r\n      const handled = this.shortcuts.handleKeydown(event);\r\n      \r\n      // Call user callback if provided\r\n      if (!handled && this.options.onKeydown) {\r\n        this.options.onKeydown(event, this);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Handle smart list continuation\r\n     * @returns {boolean} Whether the event was handled\r\n     */\r\n    handleSmartListContinuation() {\r\n      const textarea = this.textarea;\r\n      const cursorPos = textarea.selectionStart;\r\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\r\n      \r\n      if (!context || !context.inList) return false;\r\n      \r\n      // Handle empty list item (exit list)\r\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\r\n        this.deleteListMarker(context);\r\n        return true;\r\n      }\r\n      \r\n      // Handle text splitting if cursor is in middle of content\r\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\r\n        this.splitListItem(context, cursorPos);\r\n      } else {\r\n        // Just add new item after current line\r\n        this.insertNewListItem(context);\r\n      }\r\n      \r\n      // Handle numbered list renumbering\r\n      if (context.listType === 'numbered') {\r\n        this.scheduleNumberedListUpdate();\r\n      }\r\n      \r\n      return true;\r\n    }\r\n    \r\n    /**\r\n     * Delete list marker and exit list\r\n     * @private\r\n     */\r\n    deleteListMarker(context) {\r\n      // Select from line start to marker end\r\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\r\n      document.execCommand('delete');\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Insert new list item\r\n     * @private\r\n     */\r\n    insertNewListItem(context) {\r\n      const newItem = MarkdownParser.createNewListItem(context);\r\n      document.execCommand('insertText', false, '\\n' + newItem);\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Split list item at cursor position\r\n     * @private\r\n     */\r\n    splitListItem(context, cursorPos) {\r\n      // Get text after cursor\r\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\r\n      \r\n      // Delete text after cursor\r\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\r\n      document.execCommand('delete');\r\n      \r\n      // Insert new list item with remaining text\r\n      const newItem = MarkdownParser.createNewListItem(context);\r\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\r\n      \r\n      // Position cursor after new list marker\r\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\r\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Schedule numbered list renumbering\r\n     * @private\r\n     */\r\n    scheduleNumberedListUpdate() {\r\n      // Clear any pending update\r\n      if (this.numberUpdateTimeout) {\r\n        clearTimeout(this.numberUpdateTimeout);\r\n      }\r\n      \r\n      // Schedule update after current input cycle\r\n      this.numberUpdateTimeout = setTimeout(() => {\r\n        this.updateNumberedLists();\r\n      }, 10);\r\n    }\r\n    \r\n    /**\r\n     * Update/renumber all numbered lists\r\n     * @private\r\n     */\r\n    updateNumberedLists() {\r\n      const value = this.textarea.value;\r\n      const cursorPos = this.textarea.selectionStart;\r\n      \r\n      const newValue = MarkdownParser.renumberLists(value);\r\n      \r\n      if (newValue !== value) {\r\n        // Calculate cursor offset\r\n        let offset = 0;\r\n        const oldLines = value.split('\\n');\r\n        const newLines = newValue.split('\\n');\r\n        let charCount = 0;\r\n        \r\n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\r\n          if (oldLines[i] !== newLines[i]) {\r\n            const diff = newLines[i].length - oldLines[i].length;\r\n            if (charCount + oldLines[i].length < cursorPos) {\r\n              offset += diff;\r\n            }\r\n          }\r\n          charCount += oldLines[i].length + 1; // +1 for newline\r\n        }\r\n        \r\n        // Update textarea\r\n        this.textarea.value = newValue;\r\n        const newCursorPos = cursorPos + offset;\r\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\r\n        \r\n        // Trigger update\r\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Handle scroll events\r\n     * @private\r\n     */\r\n    handleScroll(event) {\r\n      // Sync preview scroll with textarea\r\n      this.preview.scrollTop = this.textarea.scrollTop;\r\n      this.preview.scrollLeft = this.textarea.scrollLeft;\r\n    }\r\n\r\n    /**\r\n     * Get editor content\r\n     * @returns {string} Current markdown content\r\n     */\r\n    getValue() {\r\n      return this.textarea.value;\r\n    }\r\n\r\n    /**\r\n     * Set editor content\r\n     * @param {string} value - Markdown content to set\r\n     */\r\n    setValue(value) {\r\n      this.textarea.value = value;\r\n      this.updatePreview();\r\n\r\n      // Update height if auto-resize is enabled\r\n      if (this.options.autoResize) {\r\n        this._updateAutoHeight();\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Execute an action by ID\r\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\r\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\r\n     * @param {Event|null} event - Optional event that triggered the action\r\n     * @returns {Promise} Whether the action was executed successfully\r\n     */\r\n    async performAction(actionId, event = null) {\r\n      const textarea = this.textarea;\r\n      if (!textarea) return false;\r\n\r\n      const action = this.actionsById?.[actionId];\r\n      if (!action) {\r\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\r\n        return false;\r\n      }\r\n\r\n      textarea.focus();\r\n\r\n      try {\r\n        await action({\r\n          editor: this,\r\n          getValue: () => this.getValue(),\r\n          setValue: (value) => this.setValue(value),\r\n          event\r\n        });\r\n        // Note: actions are responsible for dispatching input event\r\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\r\n        return true;\r\n      } catch (error) {\r\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\r\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\r\n          detail: { actionId, error }\r\n        }));\r\n        return false;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Get the rendered HTML of the current content\r\n     * @param {Object} options - Rendering options\r\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\r\n     * @returns {string} Rendered HTML\r\n     */\r\n    getRenderedHTML(options = {}) {\r\n      const markdown = this.getValue();\r\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\r\n\r\n      if (options.cleanHTML) {\r\n        // Remove all syntax marker spans for clean HTML export\r\n        html = html.replace(/.*?<\\/span>/g, '');\r\n        // Remove OverType-specific classes\r\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\r\n        // Clean up empty class attributes\r\n        html = html.replace(/\\sclass=\"\"/g, '');\r\n      }\r\n      \r\n      return html;\r\n    }\r\n\r\n    /**\r\n     * Get the current preview element's HTML\r\n     * This includes all syntax markers and OverType styling\r\n     * @returns {string} Current preview HTML (as displayed)\r\n     */\r\n    getPreviewHTML() {\r\n      return this.preview.innerHTML;\r\n    }\r\n    \r\n    /**\r\n     * Get clean HTML without any OverType-specific markup\r\n     * Useful for exporting to other formats or storage\r\n     * @returns {string} Clean HTML suitable for export\r\n     */\r\n    getCleanHTML() {\r\n      return this.getRenderedHTML({ cleanHTML: true });\r\n    }\r\n\r\n    /**\r\n     * Focus the editor\r\n     */\r\n    focus() {\r\n      this.textarea.focus();\r\n    }\r\n\r\n    /**\r\n     * Blur the editor\r\n     */\r\n    blur() {\r\n      this.textarea.blur();\r\n    }\r\n\r\n    /**\r\n     * Check if editor is initialized\r\n     * @returns {boolean}\r\n     */\r\n    isInitialized() {\r\n      return this.initialized;\r\n    }\r\n\r\n    /**\r\n     * Re-initialize with new options\r\n     * @param {Object} options - New options to apply\r\n     */\r\n    reinit(options = {}) {\r\n      const prevToolbarButtons = this.options?.toolbarButtons;\r\n      this.options = this._mergeOptions({ ...this.options, ...options });\r\n      const toolbarNeedsRebuild = this.toolbar &&\r\n        this.options.toolbar &&\r\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\r\n\r\n      // Rebuild action map in case toolbarButtons changed\r\n      this._rebuildActionsMap();\r\n\r\n      if (toolbarNeedsRebuild) {\r\n        this._cleanupToolbarListeners();\r\n        this.toolbar.destroy();\r\n        this.toolbar = null;\r\n        this._createToolbar();\r\n      }\r\n\r\n      this._applyOptions();\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Set theme for this instance\r\n     * @param {string|Object} theme - Theme name or custom theme object\r\n     * @returns {this} Returns this for chaining\r\n     */\r\n    setTheme(theme) {\r\n      // Clean up existing auto theme listener if any\r\n      this._cleanupAutoThemeListener();\r\n\r\n      // Update instance theme\r\n      this.instanceTheme = theme;\r\n\r\n      // Handle auto theme\r\n      if (theme === 'auto') {\r\n        this._setupAutoThemeListener();\r\n        // Apply the initial resolved theme\r\n        const resolvedTheme = resolveAutoTheme('auto');\r\n        this._applyResolvedTheme(resolvedTheme);\r\n      } else {\r\n        // Get theme object for non-auto themes\r\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\r\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n\r\n        // Update container theme attribute\r\n        if (themeName) {\r\n          this.container.setAttribute('data-theme', themeName);\r\n        }\r\n\r\n        // Apply CSS variables to container for instance override\r\n        if (themeObj && themeObj.colors) {\r\n          const cssVars = themeToCSSVars(themeObj.colors);\r\n          this.container.style.cssText += cssVars;\r\n        }\r\n\r\n        // Update preview to reflect new theme\r\n        this.updatePreview();\r\n      }\r\n\r\n      return this;\r\n    }\r\n\r\n    /**\r\n     * Apply a resolved theme name (used by auto theme)\r\n     * @private\r\n     * @param {string} themeName - Resolved theme name\r\n     */\r\n    _applyResolvedTheme(themeName) {\r\n      const themeObj = getTheme(themeName);\r\n      \r\n      // Update container with resolved theme, but keep auto in data-theme for tracking\r\n      this.container.setAttribute('data-theme', 'auto');\r\n      this.container.setAttribute('data-resolved-theme', themeName);\r\n\r\n      // Apply CSS variables\r\n      if (themeObj && themeObj.colors) {\r\n        const cssVars = themeToCSSVars(themeObj.colors);\r\n        this.container.style.cssText += cssVars;\r\n      }\r\n\r\n      // Update preview to reflect new theme\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Setup auto theme listener for instance\r\n     * @private\r\n     */\r\n    _setupAutoThemeListener() {\r\n      if (!window.matchMedia) return;\r\n\r\n      this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n      this.autoThemeListener = (event) => {\r\n        const resolvedTheme = event.matches ? 'cave' : 'solar';\r\n        this._applyResolvedTheme(resolvedTheme);\r\n      };\r\n\r\n      // Use addEventListener if available (modern browsers)\r\n      if (this.autoThemeMediaQuery.addEventListener) {\r\n        this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener);\r\n      } else if (this.autoThemeMediaQuery.addListener) {\r\n        // Fallback for older browsers\r\n        this.autoThemeMediaQuery.addListener(this.autoThemeListener);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Clean up auto theme listener for instance\r\n     * @private\r\n     */\r\n    _cleanupAutoThemeListener() {\r\n      if (this.autoThemeMediaQuery && this.autoThemeListener) {\r\n        if (this.autoThemeMediaQuery.removeEventListener) {\r\n          this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener);\r\n        } else if (this.autoThemeMediaQuery.removeListener) {\r\n          // Fallback for older browsers\r\n          this.autoThemeMediaQuery.removeListener(this.autoThemeListener);\r\n        }\r\n        this.autoThemeMediaQuery = null;\r\n        this.autoThemeListener = null;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Set instance-specific code highlighter\r\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n     */\r\n    setCodeHighlighter(highlighter) {\r\n      this.options.codeHighlighter = highlighter;\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Update stats bar\r\n     * @private\r\n     */\r\n    _updateStats() {\r\n      if (!this.statsBar) return;\r\n      \r\n      const value = this.textarea.value;\r\n      const lines = value.split('\\n');\r\n      const chars = value.length;\r\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\r\n      \r\n      // Calculate line and column\r\n      const selectionStart = this.textarea.selectionStart;\r\n      const beforeCursor = value.substring(0, selectionStart);\r\n      const linesBeforeCursor = beforeCursor.split('\\n');\r\n      const currentLine = linesBeforeCursor.length;\r\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\r\n      \r\n      // Use custom formatter if provided\r\n      if (this.options.statsFormatter) {\r\n        this.statsBar.innerHTML = this.options.statsFormatter({\r\n          chars,\r\n          words,\r\n          lines: lines.length,\r\n          line: currentLine,\r\n          column: currentColumn\r\n        });\r\n      } else {\r\n        // Default format with live dot\r\n        this.statsBar.innerHTML = `\r\n          
    \r\n \r\n ${chars} chars, ${words} words, ${lines.length} lines\r\n
    \r\n
    Line ${currentLine}, Col ${currentColumn}
    \r\n `;\r\n }\r\n }\r\n \r\n /**\r\n * Setup auto-resize functionality\r\n * @private\r\n */\r\n _setupAutoResize() {\r\n // Add auto-resize class for styling\r\n this.container.classList.add('overtype-auto-resize');\r\n \r\n // Store previous height for comparison\r\n this.previousHeight = null;\r\n \r\n // Initial height update\r\n this._updateAutoHeight();\r\n \r\n // Listen for input events\r\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\r\n \r\n // Listen for window resize\r\n window.addEventListener('resize', () => this._updateAutoHeight());\r\n }\r\n \r\n /**\r\n * Update height based on scrollHeight\r\n * @private\r\n */\r\n _updateAutoHeight() {\r\n if (!this.options.autoResize) return;\r\n \r\n const textarea = this.textarea;\r\n const preview = this.preview;\r\n const wrapper = this.wrapper;\r\n \r\n // Get computed styles\r\n const computed = window.getComputedStyle(textarea);\r\n const paddingTop = parseFloat(computed.paddingTop);\r\n const paddingBottom = parseFloat(computed.paddingBottom);\r\n \r\n // Store scroll positions\r\n const scrollTop = textarea.scrollTop;\r\n \r\n // Reset height to get accurate scrollHeight\r\n textarea.style.setProperty('height', 'auto', 'important');\r\n \r\n // Calculate new height based on scrollHeight\r\n let newHeight = textarea.scrollHeight;\r\n \r\n // Apply min height constraint\r\n if (this.options.minHeight) {\r\n const minHeight = parseInt(this.options.minHeight);\r\n newHeight = Math.max(newHeight, minHeight);\r\n }\r\n \r\n // Apply max height constraint\r\n let overflow = 'hidden';\r\n if (this.options.maxHeight) {\r\n const maxHeight = parseInt(this.options.maxHeight);\r\n if (newHeight > maxHeight) {\r\n newHeight = maxHeight;\r\n overflow = 'auto';\r\n }\r\n }\r\n \r\n // Apply the new height to all elements with !important to override base styles\r\n const heightPx = newHeight + 'px';\r\n textarea.style.setProperty('height', heightPx, 'important');\r\n textarea.style.setProperty('overflow-y', overflow, 'important');\r\n \r\n preview.style.setProperty('height', heightPx, 'important');\r\n preview.style.setProperty('overflow-y', overflow, 'important');\r\n \r\n wrapper.style.setProperty('height', heightPx, 'important');\r\n \r\n // Restore scroll position\r\n textarea.scrollTop = scrollTop;\r\n preview.scrollTop = scrollTop;\r\n \r\n // Track if height changed\r\n if (this.previousHeight !== newHeight) {\r\n this.previousHeight = newHeight;\r\n // Could dispatch a custom event here if needed\r\n }\r\n }\r\n \r\n /**\r\n * Show or hide stats bar\r\n * @param {boolean} show - Whether to show stats\r\n */\r\n showStats(show) {\r\n this.options.showStats = show;\r\n\r\n if (show && !this.statsBar) {\r\n // Create stats bar (add to container, not wrapper)\r\n this.statsBar = document.createElement('div');\r\n this.statsBar.className = 'overtype-stats';\r\n this.container.appendChild(this.statsBar);\r\n this._updateStats();\r\n } else if (show && this.statsBar) {\r\n // Already visible - refresh stats (useful after changing statsFormatter)\r\n this._updateStats();\r\n } else if (!show && this.statsBar) {\r\n // Remove stats bar\r\n this.statsBar.remove();\r\n this.statsBar = null;\r\n }\r\n }\r\n \r\n /**\r\n * Show normal edit mode (overlay with markdown preview)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showNormalEditMode() {\r\n this.container.dataset.mode = 'normal';\r\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\r\n\r\n // Always sync scroll from preview to textarea\r\n requestAnimationFrame(() => {\r\n this.textarea.scrollTop = this.preview.scrollTop;\r\n this.textarea.scrollLeft = this.preview.scrollLeft;\r\n });\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Show plain textarea mode (no overlay)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showPlainTextarea() {\r\n this.container.dataset.mode = 'plain';\r\n\r\n // Update toolbar button if exists\r\n if (this.toolbar) {\r\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\r\n if (toggleBtn) {\r\n toggleBtn.classList.remove('active');\r\n toggleBtn.title = 'Show markdown preview';\r\n }\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Show preview mode (read-only view)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showPreviewMode() {\r\n this.container.dataset.mode = 'preview';\r\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\r\n return this;\r\n }\r\n\r\n /**\r\n * Destroy the editor instance\r\n */\r\n destroy() {\r\n // Clean up auto theme listener\r\n this._cleanupAutoThemeListener();\r\n\r\n // Remove instance reference\r\n this.element.overTypeInstance = null;\r\n OverType.instances.delete(this.element);\r\n\r\n // Cleanup shortcuts\r\n if (this.shortcuts) {\r\n this.shortcuts.destroy();\r\n }\r\n\r\n // Remove DOM if created by us\r\n if (this.wrapper) {\r\n const content = this.getValue();\r\n this.wrapper.remove();\r\n \r\n // Restore original content\r\n this.element.textContent = content;\r\n }\r\n\r\n this.initialized = false;\r\n }\r\n\r\n // ===== Static Methods =====\r\n\r\n /**\r\n * Initialize multiple editors (static convenience method)\r\n * @param {string|Element|NodeList|Array} target - Target element(s)\r\n * @param {Object} options - Configuration options\r\n * @returns {Array} Array of OverType instances\r\n */\r\n static init(target, options = {}) {\r\n return new OverType(target, options);\r\n }\r\n\r\n /**\r\n * Initialize editors with options from data-ot-* attributes\r\n * @param {string} selector - CSS selector for target elements\r\n * @param {Object} defaults - Default options (data attrs override these)\r\n * @returns {Array} Array of OverType instances\r\n * @example\r\n * // HTML:
    \r\n * OverType.initFromData('.editor', { fontSize: '14px' });\r\n */\r\n static initFromData(selector, defaults = {}) {\r\n const elements = document.querySelectorAll(selector);\r\n return Array.from(elements).map(el => {\r\n const options = { ...defaults };\r\n\r\n // Parse data-ot-* attributes (kebab-case to camelCase)\r\n for (const attr of el.attributes) {\r\n if (attr.name.startsWith('data-ot-')) {\r\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\r\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\r\n options[key] = OverType._parseDataValue(attr.value);\r\n }\r\n }\r\n\r\n return new OverType(el, options);\r\n });\r\n }\r\n\r\n /**\r\n * Parse a data attribute value to the appropriate type\r\n * @private\r\n */\r\n static _parseDataValue(value) {\r\n if (value === 'true') return true;\r\n if (value === 'false') return false;\r\n if (value === 'null') return null;\r\n if (value !== '' && !isNaN(Number(value))) return Number(value);\r\n return value;\r\n }\r\n\r\n /**\r\n * Get instance from element\r\n * @param {Element} element - DOM element\r\n * @returns {OverType|null} OverType instance or null\r\n */\r\n static getInstance(element) {\r\n return element.overTypeInstance || OverType.instances.get(element) || null;\r\n }\r\n\r\n /**\r\n * Destroy all instances\r\n */\r\n static destroyAll() {\r\n const elements = document.querySelectorAll('[data-overtype-instance]');\r\n elements.forEach(element => {\r\n const instance = OverType.getInstance(element);\r\n if (instance) {\r\n instance.destroy();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Inject styles into the document\r\n * @param {boolean} force - Force re-injection\r\n */\r\n static injectStyles(force = false) {\r\n if (OverType.stylesInjected && !force) return;\r\n\r\n // Remove any existing OverType styles\r\n const existing = document.querySelector('style.overtype-styles');\r\n if (existing) {\r\n existing.remove();\r\n }\r\n\r\n // Generate and inject new styles with current theme\r\n const theme = OverType.currentTheme || solar;\r\n const styles = generateStyles({ theme });\r\n const styleEl = document.createElement('style');\r\n styleEl.className = 'overtype-styles';\r\n styleEl.textContent = styles;\r\n document.head.appendChild(styleEl);\r\n\r\n OverType.stylesInjected = true;\r\n }\r\n \r\n /**\r\n * Set global theme for all OverType instances\r\n * @param {string|Object} theme - Theme name or custom theme object\r\n * @param {Object} customColors - Optional color overrides\r\n */\r\n static setTheme(theme, customColors = null) {\r\n // Clean up existing auto theme listener\r\n OverType._cleanupGlobalAutoThemeListener();\r\n\r\n // Handle auto theme at global level\r\n if (theme === 'auto') {\r\n OverType._setupGlobalAutoThemeListener();\r\n // Apply the initial resolved theme\r\n const resolvedTheme = resolveAutoTheme('auto');\r\n OverType._applyGlobalResolvedTheme(resolvedTheme, customColors);\r\n } else {\r\n // Process theme\r\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\r\n\r\n // Apply custom colors if provided\r\n if (customColors) {\r\n themeObj = mergeTheme(themeObj, customColors);\r\n }\r\n\r\n // Store as current theme\r\n OverType.currentTheme = themeObj;\r\n\r\n // Re-inject styles with new theme\r\n OverType.injectStyles(true);\r\n\r\n // Update all existing instances - update container theme attribute\r\n document.querySelectorAll('.overtype-container').forEach(container => {\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n if (themeName) {\r\n container.setAttribute('data-theme', themeName);\r\n }\r\n });\r\n\r\n // Also handle any old-style wrappers without containers\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n if (!wrapper.closest('.overtype-container')) {\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n if (themeName) {\r\n wrapper.setAttribute('data-theme', themeName);\r\n }\r\n }\r\n\r\n // Trigger preview update for the instance\r\n const instance = wrapper._instance;\r\n if (instance) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components (shadow DOM instances)\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n // Set the theme attribute to update the theme name\r\n if (themeName && typeof webComponent.setAttribute === 'function') {\r\n webComponent.setAttribute('theme', themeName);\r\n }\r\n // Also call refreshTheme() to handle cases where the theme name stays the same\r\n // but the theme object's properties have changed\r\n if (typeof webComponent.refreshTheme === 'function') {\r\n webComponent.refreshTheme();\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Apply a resolved theme globally (used by auto theme)\r\n * @private\r\n * @param {string} themeName - Resolved theme name\r\n * @param {Object} customColors - Optional color overrides\r\n */\r\n static _applyGlobalResolvedTheme(themeName, customColors = null) {\r\n let themeObj = getTheme(themeName);\r\n\r\n // Apply custom colors if provided\r\n if (customColors) {\r\n themeObj = mergeTheme(themeObj, customColors);\r\n }\r\n\r\n // Store as current theme\r\n OverType.currentTheme = themeObj;\r\n\r\n // Re-inject styles with new theme\r\n OverType.injectStyles(true);\r\n\r\n // Update all containers with resolved theme, but keep 'auto' for tracking\r\n document.querySelectorAll('.overtype-container').forEach(container => {\r\n container.setAttribute('data-theme', 'auto');\r\n container.setAttribute('data-resolved-theme', themeName);\r\n });\r\n\r\n // Also handle any old-style wrappers without containers\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n if (!wrapper.closest('.overtype-container')) {\r\n wrapper.setAttribute('data-theme', 'auto');\r\n wrapper.setAttribute('data-resolved-theme', themeName);\r\n }\r\n\r\n // Trigger preview update for the instance\r\n const instance = wrapper._instance;\r\n if (instance) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.setAttribute === 'function') {\r\n webComponent.setAttribute('theme', 'auto');\r\n webComponent.setAttribute('data-resolved-theme', themeName);\r\n }\r\n if (typeof webComponent.refreshTheme === 'function') {\r\n webComponent.refreshTheme();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Setup global auto theme listener\r\n * @private\r\n */\r\n static _setupGlobalAutoThemeListener() {\r\n if (!window.matchMedia) return;\r\n\r\n OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n OverType.autoThemeListener = (event) => {\r\n const resolvedTheme = event.matches ? 'cave' : 'solar';\r\n OverType._applyGlobalResolvedTheme(resolvedTheme);\r\n };\r\n\r\n // Use addEventListener if available (modern browsers)\r\n if (OverType.autoThemeMediaQuery.addEventListener) {\r\n OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener);\r\n } else if (OverType.autoThemeMediaQuery.addListener) {\r\n // Fallback for older browsers\r\n OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener);\r\n }\r\n }\r\n\r\n /**\r\n * Clean up global auto theme listener\r\n * @private\r\n */\r\n static _cleanupGlobalAutoThemeListener() {\r\n if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) {\r\n if (OverType.autoThemeMediaQuery.removeEventListener) {\r\n OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener);\r\n } else if (OverType.autoThemeMediaQuery.removeListener) {\r\n // Fallback for older browsers\r\n OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener);\r\n }\r\n OverType.autoThemeMediaQuery = null;\r\n OverType.autoThemeListener = null;\r\n }\r\n }\r\n\r\n /**\r\n * Set global code highlighter for all OverType instances\r\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n */\r\n static setCodeHighlighter(highlighter) {\r\n MarkdownParser.setCodeHighlighter(highlighter);\r\n\r\n // Update all existing instances in light DOM\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n const instance = wrapper._instance;\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components (shadow DOM instances)\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.getEditor === 'function') {\r\n const instance = webComponent.getEditor();\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Set custom syntax processor for extending markdown parsing\r\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\r\n * @example\r\n * OverType.setCustomSyntax((html) => {\r\n * // Highlight footnote references [^1]\r\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\r\n * });\r\n */\r\n static setCustomSyntax(processor) {\r\n MarkdownParser.setCustomSyntax(processor);\r\n\r\n // Update all existing instances\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n const instance = wrapper._instance;\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.getEditor === 'function') {\r\n const instance = webComponent.getEditor();\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Initialize global event listeners\r\n */\r\n static initGlobalListeners() {\r\n if (OverType.globalListenersInitialized) return;\r\n\r\n // Input event\r\n document.addEventListener('input', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleInput(e);\r\n }\r\n });\r\n\r\n // Keydown event\r\n document.addEventListener('keydown', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleKeydown(e);\r\n }\r\n });\r\n\r\n // Scroll event\r\n document.addEventListener('scroll', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleScroll(e);\r\n }\r\n }, true);\r\n\r\n // Selection change event\r\n document.addEventListener('selectionchange', (e) => {\r\n const activeElement = document.activeElement;\r\n if (activeElement && activeElement.classList.contains('overtype-input')) {\r\n const wrapper = activeElement.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) {\r\n // Update stats bar for cursor position\r\n if (instance.options.showStats && instance.statsBar) {\r\n instance._updateStats();\r\n }\r\n // Debounce updates\r\n clearTimeout(instance._selectionTimeout);\r\n instance._selectionTimeout = setTimeout(() => {\r\n instance.updatePreview();\r\n }, 50);\r\n }\r\n }\r\n });\r\n\r\n OverType.globalListenersInitialized = true;\r\n }\r\n}\r\n\r\n// Export classes for advanced usage\r\nOverType.MarkdownParser = MarkdownParser;\r\nOverType.ShortcutsManager = ShortcutsManager;\r\n\r\n// Export theme utilities\r\nOverType.themes = { solar, cave: getTheme('cave') };\r\nOverType.getTheme = getTheme;\r\n\r\n// Set default theme\r\nOverType.currentTheme = solar;\r\n\r\n// Export for module systems\r\nexport default OverType;\r\nexport { OverType };\r\n\r\n// Export toolbar buttons for custom toolbar configurations\r\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\r\n", "/**\r\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\r\n *\r\n * Key principles:\r\n * - Every character must occupy the exact same position as in the textarea\r\n * - No font-size changes, no padding/margin on inline elements\r\n * - Markdown tokens remain visible but styled\r\n */\r\nexport class MarkdownParser {\r\n // Track link index for anchor naming\r\n static linkIndex = 0;\r\n\r\n // Global code highlighter function\r\n static codeHighlighter = null;\r\n\r\n // Custom syntax processor function\r\n static customSyntax = null;\r\n\r\n /**\r\n * Reset link index (call before parsing a new document)\r\n */\r\n static resetLinkIndex() {\r\n this.linkIndex = 0;\r\n }\r\n\r\n /**\r\n * Set global code highlighter function\r\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n */\r\n static setCodeHighlighter(highlighter) {\r\n this.codeHighlighter = highlighter;\r\n }\r\n\r\n /**\r\n * Set custom syntax processor function\r\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\r\n */\r\n static setCustomSyntax(processor) {\r\n this.customSyntax = processor;\r\n }\r\n\r\n /**\r\n * Apply custom syntax processor to parsed HTML\r\n * @param {string} html - Parsed HTML line\r\n * @returns {string} HTML with custom syntax applied\r\n */\r\n static applyCustomSyntax(html) {\r\n if (this.customSyntax) {\r\n return this.customSyntax(html);\r\n }\r\n return html;\r\n }\r\n\r\n /**\r\n * Escape HTML special characters\r\n * @param {string} text - Raw text to escape\r\n * @returns {string} Escaped HTML-safe text\r\n */\r\n static escapeHtml(text) {\r\n const map = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": '''\r\n };\r\n return text.replace(/[&<>\"']/g, m => map[m]);\r\n }\r\n\r\n /**\r\n * Preserve leading spaces as non-breaking spaces\r\n * @param {string} html - HTML string\r\n * @param {string} originalLine - Original line with spaces\r\n * @returns {string} HTML with preserved indentation\r\n */\r\n static preserveIndentation(html, originalLine) {\r\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\r\n const indentation = leadingSpaces.replace(/ /g, ' ');\r\n return html.replace(/^\\s*/, indentation);\r\n }\r\n\r\n /**\r\n * Parse headers (h1-h3 only)\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed HTML with header styling\r\n */\r\n static parseHeader(html) {\r\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\r\n const level = hashes.length;\r\n return `${hashes} ${content}`;\r\n });\r\n }\r\n\r\n /**\r\n * Parse horizontal rules\r\n * @param {string} html - HTML line to parse\r\n * @returns {string|null} Parsed horizontal rule or null\r\n */\r\n static parseHorizontalRule(html) {\r\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\r\n return `
    ${html}
    `;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse blockquotes\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed blockquote\r\n */\r\n static parseBlockquote(html) {\r\n return html.replace(/^> (.+)$/, (match, content) => {\r\n return `> ${content}`;\r\n });\r\n }\r\n\r\n /**\r\n * Parse bullet lists\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed bullet list item\r\n */\r\n static parseBulletList(html) {\r\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\r\n return `${indent}
  • ${marker} ${content}
  • `;\r\n });\r\n }\r\n\r\n /**\r\n * Parse task lists (GitHub Flavored Markdown checkboxes)\r\n * @param {string} html - HTML line to parse\r\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\r\n * @returns {string} Parsed task list item\r\n */\r\n static parseTaskList(html, isPreviewMode = false) {\r\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\r\n if (isPreviewMode) {\r\n // Preview mode: render actual checkbox\r\n const isChecked = checked.toLowerCase() === 'x';\r\n return `${indent}
  • ${content}
  • `;\r\n } else {\r\n // Normal mode: keep syntax visible for alignment\r\n return `${indent}
  • - [${checked}] ${content}
  • `;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Parse numbered lists\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed numbered list item\r\n */\r\n static parseNumberedList(html) {\r\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\r\n return `${indent}
  • ${marker} ${content}
  • `;\r\n });\r\n }\r\n\r\n /**\r\n * Parse code blocks (markers only)\r\n * @param {string} html - HTML line to parse\r\n * @returns {string|null} Parsed code fence or null\r\n */\r\n static parseCodeBlock(html) {\r\n // The line must start with three backticks and have no backticks after subsequent text\r\n const codeFenceRegex = /^`{3}[^`]*$/;\r\n if (codeFenceRegex.test(html)) {\r\n return `
    ${html}
    `;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse bold text\r\n * @param {string} html - HTML with potential bold markdown\r\n * @returns {string} HTML with bold styling\r\n */\r\n static parseBold(html) {\r\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\r\n html = html.replace(/__(.+?)__/g, '__$1__');\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse italic text\r\n * Note: Uses lookbehind assertions - requires modern browsers\r\n * @param {string} html - HTML with potential italic markdown\r\n * @returns {string} HTML with italic styling\r\n */\r\n static parseItalic(html) {\r\n // Single asterisk - must not be adjacent to other asterisks\r\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\r\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\r\n\r\n // Single underscore - must be at word boundaries to avoid matching inside words\r\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\r\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\r\n\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse strikethrough text\r\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\r\n * @param {string} html - HTML with potential strikethrough markdown\r\n * @returns {string} HTML with strikethrough styling\r\n */\r\n static parseStrikethrough(html) {\r\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\r\n html = html.replace(/(?~~$1~~');\r\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\r\n html = html.replace(/(?~$1~');\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse inline code\r\n * @param {string} html - HTML with potential code markdown\r\n * @returns {string} HTML with code styling\r\n */\r\n static parseInlineCode(html) {\r\n // Must have equal number of backticks before and after inline code\r\n //\r\n // Regex explainer:\r\n // (?$1$2$3
    ');\r\n }\r\n\r\n /**\r\n * Sanitize URL to prevent XSS attacks\r\n * @param {string} url - URL to sanitize\r\n * @returns {string} Safe URL or '#' if dangerous\r\n */\r\n static sanitizeUrl(url) {\r\n // Trim whitespace and convert to lowercase for protocol check\r\n const trimmed = url.trim();\r\n const lower = trimmed.toLowerCase();\r\n\r\n // Allow safe protocols\r\n const safeProtocols = [\r\n 'http://',\r\n 'https://',\r\n 'mailto:',\r\n 'ftp://',\r\n 'ftps://'\r\n ];\r\n\r\n // Check if URL starts with a safe protocol\r\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\r\n\r\n // Allow relative URLs (starting with / or # or no protocol)\r\n const isRelative = trimmed.startsWith('/') ||\r\n trimmed.startsWith('#') ||\r\n trimmed.startsWith('?') ||\r\n trimmed.startsWith('.') ||\r\n (!trimmed.includes(':') && !trimmed.includes('//'));\r\n\r\n // If safe protocol or relative URL, return as-is\r\n if (hasSafeProtocol || isRelative) {\r\n return url;\r\n }\r\n\r\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\r\n return '#';\r\n }\r\n\r\n /**\r\n * Parse links\r\n * @param {string} html - HTML with potential link markdown\r\n * @returns {string} HTML with link styling\r\n */\r\n static parseLinks(html) {\r\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\r\n const anchorName = `--link-${this.linkIndex++}`;\r\n // Sanitize URL to prevent XSS attacks\r\n const safeUrl = this.sanitizeUrl(url);\r\n // Use real href - pointer-events handles click prevention in normal mode\r\n return `
    [${text}](${url})`;\r\n });\r\n }\r\n\r\n /**\r\n * Identify and protect sanctuaries (code and links) before parsing\r\n * @param {string} text - Text with potential markdown\r\n * @returns {Object} Object with protected text and sanctuary map\r\n */\r\n static identifyAndProtectSanctuaries(text) {\r\n const sanctuaries = new Map();\r\n let sanctuaryCounter = 0;\r\n let protectedText = text;\r\n \r\n // Create a map to track protected regions (URLs should not be processed)\r\n const protectedRegions = [];\r\n \r\n // First, find all links and mark their URL regions as protected\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n let linkMatch;\r\n while ((linkMatch = linkRegex.exec(text)) !== null) {\r\n // Calculate the exact position of the URL part\r\n // linkMatch.index is the start of the match\r\n // We need to find where \"](\" starts, then add 2 to get URL start\r\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\r\n const urlStart = bracketPos + 2;\r\n const urlEnd = urlStart + linkMatch[2].length;\r\n protectedRegions.push({ start: urlStart, end: urlEnd });\r\n }\r\n \r\n // Now protect inline code, but skip if it's inside a protected region (URL)\r\n const codeRegex = /(? \r\n codeStart >= region.start && codeEnd <= region.end\r\n );\r\n \r\n if (!inProtectedRegion) {\r\n codeMatches.push({\r\n match: codeMatch[0],\r\n index: codeMatch.index,\r\n openTicks: codeMatch[1],\r\n content: codeMatch[2],\r\n closeTicks: codeMatch[3]\r\n });\r\n }\r\n }\r\n \r\n // Replace code matches from end to start to preserve indices\r\n codeMatches.sort((a, b) => b.index - a.index);\r\n codeMatches.forEach(codeInfo => {\r\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\r\n sanctuaries.set(placeholder, {\r\n type: 'code',\r\n original: codeInfo.match,\r\n openTicks: codeInfo.openTicks,\r\n content: codeInfo.content,\r\n closeTicks: codeInfo.closeTicks\r\n });\r\n protectedText = protectedText.substring(0, codeInfo.index) + \r\n placeholder + \r\n protectedText.substring(codeInfo.index + codeInfo.match.length);\r\n });\r\n \r\n // Then protect links - they can contain sanctuary placeholders for code but not raw code\r\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\r\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\r\n sanctuaries.set(placeholder, {\r\n type: 'link',\r\n original: match,\r\n linkText,\r\n url\r\n });\r\n return placeholder;\r\n });\r\n \r\n return { protectedText, sanctuaries };\r\n }\r\n \r\n /**\r\n * Restore and transform sanctuaries back to HTML\r\n * @param {string} html - HTML with sanctuary placeholders\r\n * @param {Map} sanctuaries - Map of sanctuaries to restore\r\n * @returns {string} HTML with sanctuaries restored and transformed\r\n */\r\n static restoreAndTransformSanctuaries(html, sanctuaries) {\r\n // Sort sanctuary placeholders by position to restore in order\r\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\r\n const indexA = html.indexOf(a);\r\n const indexB = html.indexOf(b);\r\n return indexA - indexB;\r\n });\r\n \r\n placeholders.forEach(placeholder => {\r\n const sanctuary = sanctuaries.get(placeholder);\r\n let replacement;\r\n \r\n if (sanctuary.type === 'code') {\r\n // Transform code sanctuary to HTML\r\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\r\n } else if (sanctuary.type === 'link') {\r\n // For links, we need to process the link text for markdown\r\n let processedLinkText = sanctuary.linkText;\r\n \r\n // First restore any sanctuary placeholders that were already in the link text\r\n // (e.g., inline code that was protected before the link)\r\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\r\n if (processedLinkText.includes(innerPlaceholder)) {\r\n if (innerSanctuary.type === 'code') {\r\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\r\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\r\n }\r\n }\r\n });\r\n \r\n // Now parse other markdown in the link text (bold, italic, etc)\r\n processedLinkText = this.parseStrikethrough(processedLinkText);\r\n processedLinkText = this.parseBold(processedLinkText);\r\n processedLinkText = this.parseItalic(processedLinkText);\r\n \r\n // Transform link sanctuary to HTML\r\n // URL should NOT be processed for markdown - use it as-is\r\n const anchorName = `--link-${this.linkIndex++}`;\r\n const safeUrl = this.sanitizeUrl(sanctuary.url);\r\n replacement = `[${processedLinkText}](${sanctuary.url})`;\r\n }\r\n \r\n html = html.replace(placeholder, replacement);\r\n });\r\n \r\n return html;\r\n }\r\n \r\n /**\r\n * Parse all inline elements in correct order\r\n * @param {string} text - Text with potential inline markdown\r\n * @returns {string} HTML with all inline styling\r\n */\r\n static parseInlineElements(text) {\r\n // Step 1: Identify and protect sanctuaries (code and links)\r\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\r\n \r\n // Step 2: Parse other inline elements on protected text\r\n let html = protectedText;\r\n html = this.parseStrikethrough(html);\r\n html = this.parseBold(html);\r\n html = this.parseItalic(html);\r\n \r\n // Step 3: Restore and transform sanctuaries\r\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\r\n \r\n return html;\r\n }\r\n\r\n /**\r\n * Parse a single line of markdown\r\n * @param {string} line - Raw markdown line\r\n * @returns {string} Parsed HTML line\r\n */\r\n static parseLine(line, isPreviewMode = false) {\r\n let html = this.escapeHtml(line);\r\n\r\n // Preserve indentation\r\n html = this.preserveIndentation(html, line);\r\n\r\n // Check for block elements first\r\n const horizontalRule = this.parseHorizontalRule(html);\r\n if (horizontalRule) return horizontalRule;\r\n\r\n const codeBlock = this.parseCodeBlock(html);\r\n if (codeBlock) return codeBlock;\r\n\r\n // Parse block elements\r\n html = this.parseHeader(html);\r\n html = this.parseBlockquote(html);\r\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\r\n html = this.parseBulletList(html);\r\n html = this.parseNumberedList(html);\r\n\r\n // Parse inline elements\r\n html = this.parseInlineElements(html);\r\n\r\n // Wrap in div to maintain line structure\r\n if (html.trim() === '') {\r\n // Intentionally use   for empty lines to maintain vertical spacing\r\n // This causes a 0->1 character count difference but preserves visual alignment\r\n return '
     
    ';\r\n }\r\n\r\n return `
    ${html}
    `;\r\n }\r\n\r\n /**\r\n * Parse full markdown text\r\n * @param {string} text - Full markdown text\r\n * @param {number} activeLine - Currently active line index (optional)\r\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Parsed HTML\r\n */\r\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\r\n // Reset link counter for each parse\r\n this.resetLinkIndex();\r\n\r\n const lines = text.split('\\n');\r\n let inCodeBlock = false;\r\n\r\n const parsedLines = lines.map((line, index) => {\r\n // Show raw markdown on active line if requested\r\n if (showActiveLineRaw && index === activeLine) {\r\n const content = this.escapeHtml(line) || ' ';\r\n return `
    ${content}
    `;\r\n }\r\n\r\n // Check if this line is a code fence\r\n const codeFenceRegex = /^```[^`]*$/;\r\n if (codeFenceRegex.test(line)) {\r\n inCodeBlock = !inCodeBlock;\r\n // Parse fence markers normally to get styled output\r\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\r\n }\r\n\r\n // If we're inside a code block, don't parse as markdown\r\n if (inCodeBlock) {\r\n const escaped = this.escapeHtml(line);\r\n const indented = this.preserveIndentation(escaped, line);\r\n return `
    ${indented || ' '}
    `;\r\n }\r\n\r\n // Otherwise, parse the markdown normally\r\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\r\n });\r\n\r\n // Join without newlines to prevent extra spacing\r\n const html = parsedLines.join('');\r\n\r\n // Apply post-processing for list consolidation\r\n return this.postProcessHTML(html, instanceHighlighter);\r\n }\r\n\r\n /**\r\n * Post-process HTML to consolidate lists and code blocks\r\n * @param {string} html - HTML to post-process\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\r\n */\r\n static postProcessHTML(html, instanceHighlighter) {\r\n // Check if we're in a browser environment\r\n if (typeof document === 'undefined' || !document) {\r\n // In Node.js environment - do manual post-processing\r\n return this.postProcessHTMLManual(html, instanceHighlighter);\r\n }\r\n\r\n // Parse HTML string into DOM\r\n const container = document.createElement('div');\r\n container.innerHTML = html;\r\n\r\n let currentList = null;\r\n let listType = null;\r\n let currentCodeBlock = null;\r\n let inCodeBlock = false;\r\n\r\n // Process all direct children - need to be careful with live NodeList\r\n const children = Array.from(container.children);\r\n\r\n for (let i = 0; i < children.length; i++) {\r\n const child = children[i];\r\n\r\n // Skip if child was already processed/removed\r\n if (!child.parentNode) continue;\r\n\r\n // Check for code fence start/end\r\n const codeFence = child.querySelector('.code-fence');\r\n if (codeFence) {\r\n const fenceText = codeFence.textContent;\r\n if (fenceText.startsWith('```')) {\r\n if (!inCodeBlock) {\r\n // Start of code block - keep fence visible, then add pre/code\r\n inCodeBlock = true;\r\n\r\n // Create the code block that will follow the fence\r\n currentCodeBlock = document.createElement('pre');\r\n const codeElement = document.createElement('code');\r\n currentCodeBlock.appendChild(codeElement);\r\n currentCodeBlock.className = 'code-block';\r\n\r\n // Extract language if present\r\n const lang = fenceText.slice(3).trim();\r\n if (lang) {\r\n codeElement.className = `language-${lang}`;\r\n }\r\n\r\n // Insert code block after the fence div (don't remove the fence)\r\n container.insertBefore(currentCodeBlock, child.nextSibling);\r\n\r\n // Store reference to the code element for adding content\r\n currentCodeBlock._codeElement = codeElement;\r\n currentCodeBlock._language = lang;\r\n currentCodeBlock._codeContent = '';\r\n continue;\r\n } else {\r\n // End of code block - apply highlighting if needed\r\n // Use instance highlighter if provided, otherwise fall back to global highlighter\r\n const highlighter = instanceHighlighter || this.codeHighlighter;\r\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\r\n try {\r\n const result = highlighter(\r\n currentCodeBlock._codeContent,\r\n currentCodeBlock._language || ''\r\n );\r\n\r\n // Check if result is a Promise (async highlighter)\r\n if (result && typeof result.then === 'function') {\r\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\r\n // Keep the plain text fallback that was already set\r\n } else {\r\n // Synchronous highlighter\r\n // Verify highlighter returned non-empty string\r\n if (result && typeof result === 'string' && result.trim()) {\r\n currentCodeBlock._codeElement.innerHTML = result;\r\n }\r\n // else: keep the plain text fallback that was already set\r\n }\r\n } catch (error) {\r\n console.warn('Code highlighting failed:', error);\r\n // Keep the plain text content as fallback\r\n }\r\n }\r\n\r\n inCodeBlock = false;\r\n currentCodeBlock = null;\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n // Check if we're in a code block - any div that's not a code fence\r\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\r\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\r\n // Add the line content to the code block content (for highlighting)\r\n if (currentCodeBlock._codeContent.length > 0) {\r\n currentCodeBlock._codeContent += '\\n';\r\n }\r\n // Get the actual text content, preserving spaces\r\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\r\n currentCodeBlock._codeContent += lineText;\r\n\r\n // Also add to the code element (fallback if no highlighter)\r\n if (codeElement.textContent.length > 0) {\r\n codeElement.textContent += '\\n';\r\n }\r\n codeElement.textContent += lineText;\r\n child.remove();\r\n continue;\r\n }\r\n\r\n // Check if this div contains a list item\r\n let listItem = null;\r\n if (child.tagName === 'DIV') {\r\n // Look for li inside the div\r\n listItem = child.querySelector('li');\r\n }\r\n\r\n if (listItem) {\r\n const isBullet = listItem.classList.contains('bullet-list');\r\n const isOrdered = listItem.classList.contains('ordered-list');\r\n\r\n if (!isBullet && !isOrdered) {\r\n currentList = null;\r\n listType = null;\r\n continue;\r\n }\r\n\r\n const newType = isBullet ? 'ul' : 'ol';\r\n\r\n // Start new list or continue current\r\n if (!currentList || listType !== newType) {\r\n currentList = document.createElement(newType);\r\n container.insertBefore(currentList, child);\r\n listType = newType;\r\n }\r\n\r\n // Extract and preserve indentation from the div before moving the list item\r\n const indentationNodes = [];\r\n for (const node of child.childNodes) {\r\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\r\n // This is a text node containing only non-breaking spaces (indentation)\r\n indentationNodes.push(node.cloneNode(true));\r\n } else if (node === listItem) {\r\n break; // Stop when we reach the list item\r\n }\r\n }\r\n\r\n // Add indentation to the list item\r\n indentationNodes.forEach(node => {\r\n listItem.insertBefore(node, listItem.firstChild);\r\n });\r\n\r\n // Move the list item to the current list\r\n currentList.appendChild(listItem);\r\n\r\n // Remove the now-empty div wrapper\r\n child.remove();\r\n } else {\r\n // Non-list element ends current list\r\n currentList = null;\r\n listType = null;\r\n }\r\n }\r\n\r\n return container.innerHTML;\r\n }\r\n\r\n /**\r\n * Manual post-processing for Node.js environments (without DOM)\r\n * @param {string} html - HTML to post-process\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Post-processed HTML\r\n */\r\n static postProcessHTMLManual(html, instanceHighlighter) {\r\n let processed = html;\r\n\r\n // Process unordered lists\r\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\r\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\r\n if (divs.length > 0) {\r\n const items = divs.map(div => {\r\n // Extract indentation and list item\r\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\r\n\r\n if (indentMatch && listItemMatch) {\r\n const indentation = indentMatch[1];\r\n const listItem = listItemMatch[0];\r\n // Insert indentation at the start of the list item content\r\n return listItem.replace(/
  • /, `
  • ${indentation}`);\r\n }\r\n return listItemMatch ? listItemMatch[0] : '';\r\n }).filter(Boolean);\r\n\r\n return '
      ' + items.join('') + '
    ';\r\n }\r\n return match;\r\n });\r\n\r\n // Process ordered lists\r\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\r\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\r\n if (divs.length > 0) {\r\n const items = divs.map(div => {\r\n // Extract indentation and list item\r\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\r\n\r\n if (indentMatch && listItemMatch) {\r\n const indentation = indentMatch[1];\r\n const listItem = listItemMatch[0];\r\n // Insert indentation at the start of the list item content\r\n return listItem.replace(/
  • /, `
  • ${indentation}`);\r\n }\r\n return listItemMatch ? listItemMatch[0] : '';\r\n }).filter(Boolean);\r\n\r\n return '
      ' + items.join('') + '
    ';\r\n }\r\n return match;\r\n });\r\n\r\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\r\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\r\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\r\n // Extract the content between fences\r\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\r\n const codeContent = lines.map(line => {\r\n // Extract text from each div - content is already escaped\r\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\r\n .replace(/ /g, ' ');\r\n return text;\r\n }).join('\\n');\r\n\r\n // Extract language from the opening fence\r\n const lang = openFence.slice(3).trim();\r\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\r\n\r\n // Apply code highlighting if available\r\n let highlightedContent = codeContent;\r\n // Use instance highlighter if provided, otherwise fall back to global highlighter\r\n const highlighter = instanceHighlighter || this.codeHighlighter;\r\n if (highlighter) {\r\n try {\r\n // CRITICAL: Decode HTML entities before passing to highlighter\r\n // In the DOM path, textContent automatically decodes entities.\r\n // In the manual path, we need to decode explicitly to avoid double-escaping.\r\n const decodedCode = codeContent\r\n .replace(/"/g, '\"')\r\n .replace(/'/g, \"'\")\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\r\n\r\n const result = highlighter(decodedCode, lang);\r\n\r\n // Check if result is a Promise (async highlighter)\r\n // Note: In Node.js context, we can't easily defer rendering, so we warn\r\n if (result && typeof result.then === 'function') {\r\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\r\n // Fall back to escaped content\r\n } else {\r\n // Synchronous highlighter - verify returned non-empty string\r\n if (result && typeof result === 'string' && result.trim()) {\r\n highlightedContent = result;\r\n }\r\n // else: keep the escaped codeContent as fallback\r\n }\r\n } catch (error) {\r\n console.warn('Code highlighting failed:', error);\r\n // Fall back to original content\r\n }\r\n }\r\n\r\n // Keep fence markers visible as separate divs, with pre/code block between them\r\n let result = `
    ${openFence}
    `;\r\n // Use highlighted content if available, otherwise use escaped content\r\n result += `
    ${highlightedContent}
    `;\r\n result += `
    ${closeFence}
    `;\r\n\r\n return result;\r\n });\r\n\r\n return processed;\r\n }\r\n\r\n /**\r\n * List pattern definitions\r\n */\r\n static LIST_PATTERNS = {\r\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\r\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\r\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\r\n };\r\n\r\n /**\r\n * Get list context at cursor position\r\n * @param {string} text - Full text content\r\n * @param {number} cursorPosition - Current cursor position\r\n * @returns {Object} List context information\r\n */\r\n static getListContext(text, cursorPosition) {\r\n // Find the line containing the cursor\r\n const lines = text.split('\\n');\r\n let currentPos = 0;\r\n let lineIndex = 0;\r\n let lineStart = 0;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const lineLength = lines[i].length;\r\n if (currentPos + lineLength >= cursorPosition) {\r\n lineIndex = i;\r\n lineStart = currentPos;\r\n break;\r\n }\r\n currentPos += lineLength + 1; // +1 for newline\r\n }\r\n\r\n const currentLine = lines[lineIndex];\r\n const lineEnd = lineStart + currentLine.length;\r\n\r\n // Check for checkbox first (most specific)\r\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\r\n if (checkboxMatch) {\r\n return {\r\n inList: true,\r\n listType: 'checkbox',\r\n indent: checkboxMatch[1],\r\n marker: '-',\r\n checked: checkboxMatch[2] === 'x',\r\n content: checkboxMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\r\n };\r\n }\r\n\r\n // Check for bullet list\r\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\r\n if (bulletMatch) {\r\n return {\r\n inList: true,\r\n listType: 'bullet',\r\n indent: bulletMatch[1],\r\n marker: bulletMatch[2],\r\n content: bulletMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\r\n };\r\n }\r\n\r\n // Check for numbered list\r\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\r\n if (numberedMatch) {\r\n return {\r\n inList: true,\r\n listType: 'numbered',\r\n indent: numberedMatch[1],\r\n marker: parseInt(numberedMatch[2]),\r\n content: numberedMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\r\n };\r\n }\r\n\r\n // Not in a list\r\n return {\r\n inList: false,\r\n listType: null,\r\n indent: '',\r\n marker: null,\r\n content: currentLine,\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart\r\n };\r\n }\r\n\r\n /**\r\n * Create a new list item based on context\r\n * @param {Object} context - List context from getListContext\r\n * @returns {string} New list item text\r\n */\r\n static createNewListItem(context) {\r\n switch (context.listType) {\r\n case 'bullet':\r\n return `${context.indent}${context.marker} `;\r\n case 'numbered':\r\n return `${context.indent}${context.marker + 1}. `;\r\n case 'checkbox':\r\n return `${context.indent}- [ ] `;\r\n default:\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Renumber all numbered lists in text\r\n * @param {string} text - Text containing numbered lists\r\n * @returns {string} Text with renumbered lists\r\n */\r\n static renumberLists(text) {\r\n const lines = text.split('\\n');\r\n const numbersByIndent = new Map();\r\n let inList = false;\r\n\r\n const result = lines.map(line => {\r\n const match = line.match(this.LIST_PATTERNS.numbered);\r\n\r\n if (match) {\r\n const indent = match[1];\r\n const indentLevel = indent.length;\r\n const content = match[3];\r\n\r\n // If we weren't in a list or indent changed, reset lower levels\r\n if (!inList) {\r\n numbersByIndent.clear();\r\n }\r\n\r\n // Get the next number for this indent level\r\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\r\n numbersByIndent.set(indentLevel, currentNumber);\r\n\r\n // Clear deeper indent levels\r\n for (const [level] of numbersByIndent) {\r\n if (level > indentLevel) {\r\n numbersByIndent.delete(level);\r\n }\r\n }\r\n\r\n inList = true;\r\n return `${indent}${currentNumber}. ${content}`;\r\n } else {\r\n // Not a numbered list item\r\n if (line.trim() === '' || !line.match(/^\\s/)) {\r\n // Empty line or non-indented line breaks the list\r\n inList = false;\r\n numbersByIndent.clear();\r\n }\r\n return line;\r\n }\r\n });\r\n\r\n return result.join('\\n');\r\n }\r\n}\r\n", "/**\r\n * Keyboard shortcuts handler for OverType editor\r\n * Delegates to editor.performAction for consistent behavior\r\n */\r\n\r\n/**\r\n * ShortcutsManager - Handles keyboard shortcuts for the editor\r\n */\r\nexport class ShortcutsManager {\r\n constructor(editor) {\r\n this.editor = editor;\r\n }\r\n\r\n /**\r\n * Handle keydown events - called by OverType\r\n * @param {KeyboardEvent} event - The keyboard event\r\n * @returns {boolean} Whether the event was handled\r\n */\r\n handleKeydown(event) {\r\n const isMac = navigator.platform.toLowerCase().includes('mac');\r\n const modKey = isMac ? event.metaKey : event.ctrlKey;\r\n\r\n if (!modKey) return false;\r\n\r\n let actionId = null;\r\n\r\n switch (event.key.toLowerCase()) {\r\n case 'b':\r\n if (!event.shiftKey) actionId = 'toggleBold';\r\n break;\r\n case 'i':\r\n if (!event.shiftKey) actionId = 'toggleItalic';\r\n break;\r\n case 'k':\r\n if (!event.shiftKey) actionId = 'insertLink';\r\n break;\r\n case '7':\r\n if (event.shiftKey) actionId = 'toggleNumberedList';\r\n break;\r\n case '8':\r\n if (event.shiftKey) actionId = 'toggleBulletList';\r\n break;\r\n }\r\n\r\n if (actionId) {\r\n event.preventDefault();\r\n this.editor.performAction(actionId, event);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy() {\r\n // Nothing to clean up since we don't add our own listener\r\n }\r\n}\r\n", "/**\r\n * Built-in themes for OverType editor\r\n * Each theme provides a complete color palette for the editor\r\n */\r\n\r\n/**\r\n * Solar theme - Light, warm and bright\r\n */\r\nexport const solar = {\r\n name: 'solar',\r\n colors: {\r\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\r\n bgSecondary: '#ffffff', // White - editor background\r\n text: '#0d3b66', // Yale Blue - main text\r\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\r\n textSecondary: '#5a7a9b', // Muted blue - secondary text\r\n h1: '#f95738', // Tomato - h1 headers\r\n h2: '#ee964b', // Sandy Brown - h2 headers\r\n h3: '#3d8a51', // Forest green - h3 headers\r\n strong: '#ee964b', // Sandy Brown - bold text\r\n em: '#f95738', // Tomato - italic text\r\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\r\n link: '#0d3b66', // Yale Blue - links\r\n code: '#0d3b66', // Yale Blue - inline code\r\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\r\n blockquote: '#5a7a9b', // Muted blue - blockquotes\r\n hr: '#5a7a9b', // Muted blue - horizontal rules\r\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\r\n syntax: '#999999', // Gray - syntax highlighting fallback\r\n cursor: '#f95738', // Tomato - cursor\r\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\r\n listMarker: '#ee964b', // Sandy Brown - list markers\r\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\r\n border: '#e0e0e0', // Light gray - borders\r\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\r\n primary: '#0d3b66', // Yale Blue - primary accent\r\n // Toolbar colors\r\n toolbarBg: '#ffffff', // White - toolbar background\r\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\r\n toolbarHover: '#f5f5f5', // Light gray - hover background\r\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\r\n }\r\n};\r\n\r\n/**\r\n * Cave theme - Dark ocean depths\r\n */\r\nexport const cave = {\r\n name: 'cave',\r\n colors: {\r\n bgPrimary: '#141E26', // Deep ocean - main background\r\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\r\n text: '#c5dde8', // Light blue-gray - main text\r\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\r\n textSecondary: '#9fcfec', // Brighter blue - secondary text\r\n h1: '#d4a5ff', // Rich lavender - h1 headers\r\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\r\n h3: '#9fcfec', // Brighter blue - h3 headers\r\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\r\n em: '#9fcfec', // Brighter blue - italic text\r\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\r\n link: '#9fcfec', // Brighter blue - links\r\n code: '#c5dde8', // Light blue-gray - inline code\r\n codeBg: '#1a232b', // Very dark blue - code background\r\n blockquote: '#9fcfec', // Brighter blue - same as italic\r\n hr: '#c5dde8', // Light blue-gray - horizontal rules\r\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\r\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\r\n cursor: '#f26419', // Orange Pantone - cursor\r\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\r\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\r\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\r\n border: '#2a3f52', // Dark blue-gray - borders\r\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\r\n primary: '#9fcfec', // Brighter blue - primary accent\r\n // Toolbar colors for dark theme\r\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\r\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\r\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\r\n toolbarActive: '#2a3f52', // Even lighter - active button background\r\n }\r\n};\r\n\r\n/**\r\n * Auto theme - Automatically switches between solar and cave based on system preference\r\n * This is a special marker theme that triggers automatic theme switching\r\n */\r\nexport const auto = {\r\n name: 'auto',\r\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\r\n colors: solar.colors // Default to solar colors for initial render\r\n};\r\n\r\n/**\r\n * Default themes registry\r\n */\r\nexport const themes = {\r\n solar,\r\n cave,\r\n auto,\r\n // Aliases for backward compatibility\r\n light: solar,\r\n dark: cave\r\n};\r\n\r\n/**\r\n * Get theme by name or return custom theme object\r\n * @param {string|Object} theme - Theme name or custom theme object\r\n * @returns {Object} Theme configuration\r\n */\r\nexport function getTheme(theme) {\r\n if (typeof theme === 'string') {\r\n const themeObj = themes[theme] || themes.solar;\r\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\r\n return { ...themeObj, name: theme };\r\n }\r\n return theme;\r\n}\r\n\r\n/**\r\n * Resolve auto theme to actual theme based on system color scheme preference\r\n * @param {string} themeName - Theme name to resolve\r\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\r\n */\r\nexport function resolveAutoTheme(themeName) {\r\n if (themeName !== 'auto') {\r\n return themeName;\r\n }\r\n\r\n // Check for system dark mode preference\r\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n return isDarkMode ? 'cave' : 'solar';\r\n}\r\n\r\n/**\r\n * Get the current system color scheme preference\r\n * @returns {string} 'dark' or 'light'\r\n */\r\nexport function getSystemColorScheme() {\r\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n return isDarkMode ? 'dark' : 'light';\r\n}\r\n\r\n/**\r\n * Apply theme colors to CSS variables\r\n * @param {Object} colors - Theme colors object\r\n * @returns {string} CSS custom properties string\r\n */\r\nexport function themeToCSSVars(colors) {\r\n const vars = [];\r\n for (const [key, value] of Object.entries(colors)) {\r\n // Convert camelCase to kebab-case\r\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n vars.push(`--${varName}: ${value};`);\r\n }\r\n return vars.join('\\n');\r\n}\r\n\r\n/**\r\n * Merge custom colors with base theme\r\n * @param {Object} baseTheme - Base theme object\r\n * @param {Object} customColors - Custom color overrides\r\n * @returns {Object} Merged theme object\r\n */\r\nexport function mergeTheme(baseTheme, customColors = {}) {\r\n return {\r\n ...baseTheme,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customColors\r\n }\r\n };\r\n}", "/**\r\n * CSS styles for OverType editor\r\n * Embedded in JavaScript to ensure single-file distribution\r\n */\r\n\r\nimport { themeToCSSVars } from './themes.js';\r\n\r\n/**\r\n * Generate the complete CSS for the editor\r\n * @param {Object} options - Configuration options\r\n * @returns {string} Complete CSS string\r\n */\r\nexport function generateStyles(options = {}) {\r\n const {\r\n fontSize = '14px',\r\n lineHeight = 1.6,\r\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\r\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\r\n padding = '20px',\r\n theme = null,\r\n mobile = {}\r\n } = options;\r\n\r\n // Generate mobile overrides\r\n const mobileStyles = Object.keys(mobile).length > 0 ? `\r\n @media (max-width: 640px) {\r\n .overtype-wrapper .overtype-input,\r\n .overtype-wrapper .overtype-preview {\r\n ${Object.entries(mobile)\r\n .map(([prop, val]) => {\r\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n return `${cssProp}: ${val} !important;`;\r\n })\r\n .join('\\n ')}\r\n }\r\n }\r\n ` : '';\r\n\r\n // Generate theme variables if provided\r\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\r\n\r\n return `\r\n /* OverType Editor Styles */\r\n \r\n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\r\n .overtype-container * {\r\n /* Box model - these commonly leak */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: 0 !important;\r\n \r\n /* Layout - these can break our layout */\r\n /* Don't reset position - it breaks dropdowns */\r\n float: none !important;\r\n clear: none !important;\r\n \r\n /* Typography - only reset decorative aspects */\r\n text-decoration: none !important;\r\n text-transform: none !important;\r\n letter-spacing: normal !important;\r\n \r\n /* Visual effects that can interfere */\r\n box-shadow: none !important;\r\n text-shadow: none !important;\r\n \r\n /* Ensure box-sizing is consistent */\r\n box-sizing: border-box !important;\r\n \r\n /* Keep inheritance for these */\r\n /* font-family, color, line-height, font-size - inherit */\r\n }\r\n \r\n /* Container base styles after reset */\r\n .overtype-container {\r\n display: flex !important;\r\n flex-direction: column !important;\r\n width: 100% !important;\r\n height: 100% !important;\r\n position: relative !important; /* Override reset - needed for absolute children */\r\n overflow: visible !important; /* Allow dropdown to overflow container */\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\r\n text-align: left !important;\r\n ${themeVars ? `\r\n /* Theme Variables */\r\n ${themeVars}` : ''}\r\n }\r\n \r\n /* Force left alignment for all elements in the editor */\r\n .overtype-container .overtype-wrapper * {\r\n text-align: left !important;\r\n }\r\n \r\n /* Auto-resize mode styles */\r\n .overtype-container.overtype-auto-resize {\r\n height: auto !important;\r\n }\r\n\r\n .overtype-container.overtype-auto-resize .overtype-wrapper {\r\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\r\n height: auto !important;\r\n min-height: 60px !important;\r\n overflow: visible !important;\r\n }\r\n \r\n .overtype-wrapper {\r\n position: relative !important; /* Override reset - needed for absolute children */\r\n width: 100% !important;\r\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\r\n min-height: 60px !important; /* Minimum usable height */\r\n overflow: hidden !important;\r\n background: var(--bg-secondary, #ffffff) !important;\r\n z-index: 1; /* Below toolbar and dropdown */\r\n }\r\n\r\n /* Critical alignment styles - must be identical for both layers */\r\n .overtype-wrapper .overtype-input,\r\n .overtype-wrapper .overtype-preview {\r\n /* Positioning - must be identical */\r\n position: absolute !important; /* Override reset - required for overlay */\r\n top: 0 !important;\r\n left: 0 !important;\r\n width: 100% !important;\r\n height: 100% !important;\r\n \r\n /* Font properties - any difference breaks alignment */\r\n font-family: ${fontFamily} !important;\r\n font-variant-ligatures: none !important; /* keep metrics stable for code */\r\n font-size: var(--instance-font-size, ${fontSize}) !important;\r\n line-height: var(--instance-line-height, ${lineHeight}) !important;\r\n font-weight: normal !important;\r\n font-style: normal !important;\r\n font-variant: normal !important;\r\n font-stretch: normal !important;\r\n font-kerning: none !important;\r\n font-feature-settings: normal !important;\r\n \r\n /* Box model - must match exactly */\r\n padding: var(--instance-padding, ${padding}) !important;\r\n margin: 0 !important;\r\n border: none !important;\r\n outline: none !important;\r\n box-sizing: border-box !important;\r\n \r\n /* Text layout - critical for character positioning */\r\n white-space: pre-wrap !important;\r\n word-wrap: break-word !important;\r\n word-break: normal !important;\r\n overflow-wrap: break-word !important;\r\n tab-size: 2 !important;\r\n -moz-tab-size: 2 !important;\r\n text-align: left !important;\r\n text-indent: 0 !important;\r\n letter-spacing: normal !important;\r\n word-spacing: normal !important;\r\n \r\n /* Text rendering */\r\n text-transform: none !important;\r\n text-rendering: auto !important;\r\n -webkit-font-smoothing: auto !important;\r\n -webkit-text-size-adjust: 100% !important;\r\n \r\n /* Direction and writing */\r\n direction: ltr !important;\r\n writing-mode: horizontal-tb !important;\r\n unicode-bidi: normal !important;\r\n text-orientation: mixed !important;\r\n \r\n /* Visual effects that could shift perception */\r\n text-shadow: none !important;\r\n filter: none !important;\r\n transform: none !important;\r\n zoom: 1 !important;\r\n \r\n /* Vertical alignment */\r\n vertical-align: baseline !important;\r\n \r\n /* Size constraints */\r\n min-width: 0 !important;\r\n min-height: 0 !important;\r\n max-width: none !important;\r\n max-height: none !important;\r\n \r\n /* Overflow */\r\n overflow-y: auto !important;\r\n overflow-x: auto !important;\r\n /* overscroll-behavior removed to allow scroll-through to parent */\r\n scrollbar-width: auto !important;\r\n scrollbar-gutter: auto !important;\r\n \r\n /* Animation/transition - disabled to prevent movement */\r\n animation: none !important;\r\n transition: none !important;\r\n }\r\n\r\n /* Input layer styles */\r\n .overtype-wrapper .overtype-input {\r\n /* Layer positioning */\r\n z-index: 1 !important;\r\n \r\n /* Text visibility */\r\n color: transparent !important;\r\n caret-color: var(--cursor, #f95738) !important;\r\n background-color: transparent !important;\r\n \r\n /* Textarea-specific */\r\n resize: none !important;\r\n appearance: none !important;\r\n -webkit-appearance: none !important;\r\n -moz-appearance: none !important;\r\n \r\n /* Prevent mobile zoom on focus */\r\n touch-action: manipulation !important;\r\n \r\n /* Disable autofill and spellcheck */\r\n autocomplete: off !important;\r\n autocorrect: off !important;\r\n autocapitalize: off !important;\r\n spellcheck: false !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-input::selection {\r\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\r\n }\r\n\r\n /* Preview layer styles */\r\n .overtype-wrapper .overtype-preview {\r\n /* Layer positioning */\r\n z-index: 0 !important;\r\n pointer-events: none !important;\r\n color: var(--text, #0d3b66) !important;\r\n background-color: transparent !important;\r\n \r\n /* Prevent text selection */\r\n user-select: none !important;\r\n -webkit-user-select: none !important;\r\n -moz-user-select: none !important;\r\n -ms-user-select: none !important;\r\n }\r\n\r\n /* Defensive styles for preview child divs */\r\n .overtype-wrapper .overtype-preview div {\r\n /* Reset any inherited styles */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: none !important;\r\n text-align: left !important;\r\n text-indent: 0 !important;\r\n display: block !important;\r\n position: static !important;\r\n transform: none !important;\r\n min-height: 0 !important;\r\n max-height: none !important;\r\n line-height: inherit !important;\r\n font-size: inherit !important;\r\n font-family: inherit !important;\r\n }\r\n\r\n /* Markdown element styling - NO SIZE CHANGES */\r\n .overtype-wrapper .overtype-preview .header {\r\n font-weight: bold !important;\r\n }\r\n\r\n /* Header colors */\r\n .overtype-wrapper .overtype-preview .h1 { \r\n color: var(--h1, #f95738) !important; \r\n }\r\n .overtype-wrapper .overtype-preview .h2 { \r\n color: var(--h2, #ee964b) !important; \r\n }\r\n .overtype-wrapper .overtype-preview .h3 { \r\n color: var(--h3, #3d8a51) !important; \r\n }\r\n\r\n /* Semantic headers - flatten in edit mode */\r\n .overtype-wrapper .overtype-preview h1,\r\n .overtype-wrapper .overtype-preview h2,\r\n .overtype-wrapper .overtype-preview h3 {\r\n font-size: inherit !important;\r\n font-weight: bold !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n display: inline !important;\r\n line-height: inherit !important;\r\n }\r\n\r\n /* Header colors for semantic headers */\r\n .overtype-wrapper .overtype-preview h1 { \r\n color: var(--h1, #f95738) !important; \r\n }\r\n .overtype-wrapper .overtype-preview h2 { \r\n color: var(--h2, #ee964b) !important; \r\n }\r\n .overtype-wrapper .overtype-preview h3 { \r\n color: var(--h3, #3d8a51) !important; \r\n }\r\n\r\n /* Lists - remove styling in edit mode */\r\n .overtype-wrapper .overtype-preview ul,\r\n .overtype-wrapper .overtype-preview ol {\r\n list-style: none !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n display: block !important; /* Lists need to be block for line breaks */\r\n }\r\n\r\n .overtype-wrapper .overtype-preview li {\r\n display: block !important; /* Each item on its own line */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n /* Don't set list-style here - let ul/ol control it */\r\n }\r\n\r\n /* Bold text */\r\n .overtype-wrapper .overtype-preview strong {\r\n color: var(--strong, #ee964b) !important;\r\n font-weight: bold !important;\r\n }\r\n\r\n /* Italic text */\r\n .overtype-wrapper .overtype-preview em {\r\n color: var(--em, #f95738) !important;\r\n text-decoration-color: var(--em, #f95738) !important;\r\n text-decoration-thickness: 1px !important;\r\n font-style: italic !important;\r\n }\r\n\r\n /* Strikethrough text */\r\n .overtype-wrapper .overtype-preview del {\r\n color: var(--del, #ee964b) !important;\r\n text-decoration: line-through !important;\r\n text-decoration-color: var(--del, #ee964b) !important;\r\n text-decoration-thickness: 1px !important;\r\n }\r\n\r\n /* Inline code */\r\n .overtype-wrapper .overtype-preview code {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n color: var(--code, #0d3b66) !important;\r\n padding: 0 !important;\r\n border-radius: 2px !important;\r\n font-family: inherit !important;\r\n font-size: inherit !important;\r\n line-height: inherit !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Code blocks - consolidated pre blocks */\r\n .overtype-wrapper .overtype-preview pre {\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n border-radius: 4px !important;\r\n overflow-x: auto !important;\r\n }\r\n \r\n /* Code block styling in normal mode - yellow background */\r\n .overtype-wrapper .overtype-preview pre.code-block {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\r\n }\r\n\r\n /* Code inside pre blocks - remove background */\r\n .overtype-wrapper .overtype-preview pre code {\r\n background: transparent !important;\r\n color: var(--code, #0d3b66) !important;\r\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\r\n }\r\n\r\n /* Blockquotes */\r\n .overtype-wrapper .overtype-preview .blockquote {\r\n color: var(--blockquote, #5a7a9b) !important;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n border: none !important;\r\n }\r\n\r\n /* Links */\r\n .overtype-wrapper .overtype-preview a {\r\n color: var(--link, #0d3b66) !important;\r\n text-decoration: underline !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-preview a:hover {\r\n text-decoration: underline !important;\r\n color: var(--link, #0d3b66) !important;\r\n }\r\n\r\n /* Lists - no list styling */\r\n .overtype-wrapper .overtype-preview ul,\r\n .overtype-wrapper .overtype-preview ol {\r\n list-style: none !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n\r\n /* Horizontal rules */\r\n .overtype-wrapper .overtype-preview hr {\r\n border: none !important;\r\n color: var(--hr, #5a7a9b) !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-preview .hr-marker {\r\n color: var(--hr, #5a7a9b) !important;\r\n opacity: 0.6 !important;\r\n }\r\n\r\n /* Code fence markers - with background when not in code block */\r\n .overtype-wrapper .overtype-preview .code-fence {\r\n color: var(--code, #0d3b66) !important;\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n }\r\n \r\n /* Code block lines - background for entire code block */\r\n .overtype-wrapper .overtype-preview .code-block-line {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n }\r\n \r\n /* Remove background from code fence when inside code block line */\r\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\r\n background: transparent !important;\r\n }\r\n\r\n /* Raw markdown line */\r\n .overtype-wrapper .overtype-preview .raw-line {\r\n color: var(--raw-line, #5a7a9b) !important;\r\n font-style: normal !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Syntax markers */\r\n .overtype-wrapper .overtype-preview .syntax-marker {\r\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\r\n opacity: 0.7 !important;\r\n }\r\n\r\n /* List markers */\r\n .overtype-wrapper .overtype-preview .list-marker {\r\n color: var(--list-marker, #ee964b) !important;\r\n }\r\n\r\n /* Stats bar */\r\n \r\n /* Stats bar - positioned by flexbox */\r\n .overtype-stats {\r\n height: 40px !important;\r\n padding: 0 20px !important;\r\n background: #f8f9fa !important;\r\n border-top: 1px solid #e0e0e0 !important;\r\n display: flex !important;\r\n justify-content: space-between !important;\r\n align-items: center !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\r\n font-size: 0.85rem !important;\r\n color: #666 !important;\r\n flex-shrink: 0 !important; /* Don't shrink */\r\n z-index: 10001 !important; /* Above link tooltip */\r\n position: relative !important; /* Enable z-index */\r\n }\r\n \r\n /* Dark theme stats bar */\r\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\r\n background: var(--bg-secondary, #1D2D3E) !important;\r\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\r\n color: var(--text, #c5dde8) !important;\r\n }\r\n \r\n .overtype-stats .overtype-stat {\r\n display: flex !important;\r\n align-items: center !important;\r\n gap: 5px !important;\r\n white-space: nowrap !important;\r\n }\r\n \r\n .overtype-stats .live-dot {\r\n width: 8px !important;\r\n height: 8px !important;\r\n background: #4caf50 !important;\r\n border-radius: 50% !important;\r\n animation: overtype-pulse 2s infinite !important;\r\n }\r\n \r\n @keyframes overtype-pulse {\r\n 0%, 100% { opacity: 1; transform: scale(1); }\r\n 50% { opacity: 0.6; transform: scale(1.2); }\r\n }\r\n \r\n\r\n /* Toolbar Styles */\r\n .overtype-toolbar {\r\n display: flex !important;\r\n align-items: center !important;\r\n gap: 4px !important;\r\n padding: 8px !important; /* Override reset */\r\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\r\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\r\n overflow-x: auto !important; /* Allow horizontal scrolling */\r\n overflow-y: hidden !important; /* Hide vertical overflow */\r\n -webkit-overflow-scrolling: touch !important;\r\n flex-shrink: 0 !important;\r\n height: auto !important;\r\n position: relative !important; /* Override reset */\r\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\r\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\r\n }\r\n \r\n /* Thin scrollbar styling */\r\n .overtype-toolbar::-webkit-scrollbar {\r\n height: 4px;\r\n }\r\n \r\n .overtype-toolbar::-webkit-scrollbar-track {\r\n background: transparent;\r\n }\r\n \r\n .overtype-toolbar::-webkit-scrollbar-thumb {\r\n background: rgba(0, 0, 0, 0.2);\r\n border-radius: 2px;\r\n }\r\n\r\n .overtype-toolbar-button {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 6px;\r\n background: transparent;\r\n color: var(--toolbar-icon, var(--text-secondary, #666));\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n\r\n .overtype-toolbar-button svg {\r\n width: 20px;\r\n height: 20px;\r\n fill: currentColor;\r\n }\r\n\r\n .overtype-toolbar-button:hover {\r\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\r\n color: var(--toolbar-icon, var(--text-primary, #333));\r\n }\r\n\r\n .overtype-toolbar-button:active {\r\n transform: scale(0.95);\r\n }\r\n\r\n .overtype-toolbar-button.active {\r\n background: var(--toolbar-active, var(--primary, #007bff));\r\n color: var(--toolbar-icon, var(--text-primary, #333));\r\n }\r\n\r\n .overtype-toolbar-button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .overtype-toolbar-separator {\r\n width: 1px;\r\n height: 24px;\r\n background: var(--border, #e0e0e0);\r\n margin: 0 4px;\r\n flex-shrink: 0;\r\n }\r\n\r\n /* Adjust wrapper when toolbar is present */\r\n /* Mobile toolbar adjustments */\r\n @media (max-width: 640px) {\r\n .overtype-toolbar {\r\n padding: 6px;\r\n gap: 2px;\r\n }\r\n\r\n .overtype-toolbar-button {\r\n width: 36px;\r\n height: 36px;\r\n }\r\n\r\n .overtype-toolbar-separator {\r\n margin: 0 2px;\r\n }\r\n }\r\n \r\n /* Plain mode - hide preview and show textarea text */\r\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\r\n display: none !important;\r\n }\r\n \r\n .overtype-container[data-mode=\"plain\"] .overtype-input {\r\n color: var(--text, #0d3b66) !important;\r\n /* Use system font stack for better plain text readability */\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \r\n \"Helvetica Neue\", Arial, sans-serif !important;\r\n }\r\n \r\n /* Ensure textarea remains transparent in overlay mode */\r\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\r\n color: transparent !important;\r\n }\r\n\r\n /* Dropdown menu styles */\r\n .overtype-toolbar-button {\r\n position: relative !important; /* Override reset - needed for dropdown */\r\n }\r\n\r\n .overtype-toolbar-button.dropdown-active {\r\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\r\n }\r\n\r\n .overtype-dropdown-menu {\r\n position: fixed !important; /* Fixed positioning relative to viewport */\r\n background: var(--bg-secondary, white) !important; /* Override reset */\r\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\r\n border-radius: 6px;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\r\n z-index: 10000; /* Very high z-index to ensure visibility */\r\n min-width: 150px;\r\n padding: 4px 0 !important; /* Override reset */\r\n /* Position will be set via JavaScript based on button position */\r\n }\r\n\r\n .overtype-dropdown-item {\r\n display: flex;\r\n align-items: center;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: none;\r\n background: none;\r\n text-align: left;\r\n cursor: pointer;\r\n font-size: 14px;\r\n color: var(--text, #333);\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\r\n }\r\n\r\n .overtype-dropdown-item:hover {\r\n background: var(--hover-bg, #f0f0f0);\r\n }\r\n\r\n .overtype-dropdown-item.active {\r\n font-weight: 600;\r\n }\r\n\r\n .overtype-dropdown-check {\r\n width: 16px;\r\n margin-right: 8px;\r\n color: var(--h1, #007bff);\r\n }\r\n\r\n .overtype-dropdown-icon {\r\n width: 20px;\r\n margin-right: 8px;\r\n text-align: center;\r\n }\r\n\r\n /* Preview mode styles */\r\n .overtype-container[data-mode=\"preview\"] .overtype-input {\r\n display: none !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\r\n pointer-events: auto !important;\r\n user-select: text !important;\r\n cursor: text !important;\r\n }\r\n\r\n /* Hide syntax markers in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\r\n display: none !important;\r\n }\r\n \r\n /* Hide URL part of links in preview mode - extra specificity */\r\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\r\n .overtype-container[data-mode=\"preview\"] .url-part {\r\n display: none !important;\r\n }\r\n \r\n /* Hide all syntax markers inside links too */\r\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\r\n display: none !important;\r\n }\r\n\r\n /* Headers - restore proper sizing in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\r\n font-weight: 600 !important;\r\n margin: 0 !important;\r\n display: block !important;\r\n color: inherit !important; /* Use parent text color */\r\n line-height: 1 !important; /* Tight line height for headings */\r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \r\n font-size: 2em !important; \r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \r\n font-size: 1.5em !important; \r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \r\n font-size: 1.17em !important; \r\n }\r\n\r\n /* Lists - restore list styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\r\n display: block !important;\r\n list-style: disc !important;\r\n padding-left: 2em !important;\r\n margin: 1em 0 !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\r\n display: block !important;\r\n list-style: decimal !important;\r\n padding-left: 2em !important;\r\n margin: 1em 0 !important;\r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\r\n display: list-item !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n /* Task list checkboxes - only in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\r\n list-style: none !important;\r\n position: relative !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\r\n margin-right: 0.5em !important;\r\n cursor: default !important;\r\n vertical-align: middle !important;\r\n }\r\n\r\n /* Task list in normal mode - keep syntax visible */\r\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\r\n list-style: none !important;\r\n }\r\n\r\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\r\n color: var(--syntax, #999999) !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Links - make clickable in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\r\n pointer-events: auto !important;\r\n cursor: pointer !important;\r\n color: var(--link, #0066cc) !important;\r\n text-decoration: underline !important;\r\n }\r\n\r\n /* Code blocks - proper pre/code styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\r\n background: #2d2d2d !important;\r\n color: #f8f8f2 !important;\r\n padding: 1.2em !important;\r\n border-radius: 3px !important;\r\n overflow-x: auto !important;\r\n margin: 0 !important;\r\n display: block !important;\r\n }\r\n \r\n /* Cave theme code block background in preview mode */\r\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\r\n background: #11171F !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\r\n background: transparent !important;\r\n color: inherit !important;\r\n padding: 0 !important;\r\n font-family: ${fontFamily} !important;\r\n font-size: 0.9em !important;\r\n line-height: 1.4 !important;\r\n }\r\n\r\n /* Hide old code block lines and fences in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\r\n display: none !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\r\n display: none !important;\r\n }\r\n\r\n /* Blockquotes - enhanced styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\r\n display: block !important;\r\n border-left: 4px solid var(--blockquote, #ddd) !important;\r\n padding-left: 1em !important;\r\n margin: 1em 0 !important;\r\n font-style: italic !important;\r\n }\r\n\r\n /* Typography improvements in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\r\n font-family: Georgia, 'Times New Roman', serif !important;\r\n font-size: 16px !important;\r\n line-height: 1.8 !important;\r\n color: var(--text, #333) !important; /* Consistent text color */\r\n }\r\n\r\n /* Inline code in preview mode - keep monospace */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\r\n font-family: ${fontFamily} !important;\r\n font-size: 0.9em !important;\r\n background: rgba(135, 131, 120, 0.15) !important;\r\n padding: 0.2em 0.4em !important;\r\n border-radius: 3px !important;\r\n }\r\n\r\n /* Strong and em elements in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\r\n font-weight: 700 !important;\r\n color: inherit !important; /* Use parent text color */\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\r\n font-style: italic !important;\r\n color: inherit !important; /* Use parent text color */\r\n }\r\n\r\n /* HR in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\r\n display: block !important;\r\n border-top: 2px solid var(--hr, #ddd) !important;\r\n text-indent: -9999px !important;\r\n height: 2px !important;\r\n }\r\n\r\n /* Link Tooltip - Base styles (all browsers) */\r\n .overtype-link-tooltip {\r\n /* Visual styles that work for both positioning methods */\r\n background: #333 !important;\r\n color: white !important;\r\n padding: 6px 10px !important;\r\n border-radius: 16px !important;\r\n font-size: 12px !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\r\n display: none !important;\r\n z-index: 10000 !important;\r\n cursor: pointer !important;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\r\n max-width: 300px !important;\r\n white-space: nowrap !important;\r\n overflow: hidden !important;\r\n text-overflow: ellipsis !important;\r\n\r\n /* Base positioning for Floating UI fallback */\r\n position: absolute;\r\n }\r\n\r\n .overtype-link-tooltip.visible {\r\n display: flex !important;\r\n }\r\n\r\n /* CSS Anchor Positioning (modern browsers only) */\r\n @supports (position-anchor: --x) and (position-area: center) {\r\n .overtype-link-tooltip {\r\n /* Only anchor positioning specific properties */\r\n position-anchor: var(--target-anchor, --link-0);\r\n position-area: block-end center;\r\n margin-top: 8px !important;\r\n position-try: most-width block-end inline-end, flip-inline, block-start center;\r\n position-visibility: anchors-visible;\r\n }\r\n }\r\n\r\n ${mobileStyles}\r\n `;\r\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\r\n * Toolbar component for OverType editor\r\n * Provides markdown formatting buttons with support for custom buttons\r\n */\r\n\r\nimport * as markdownActions from 'markdown-actions';\r\n\r\nexport class Toolbar {\r\n constructor(editor, options = {}) {\r\n this.editor = editor;\r\n this.container = null;\r\n this.buttons = {};\r\n\r\n // Get toolbar buttons array\r\n this.toolbarButtons = options.toolbarButtons || [];\r\n }\r\n\r\n /**\r\n * Create and render toolbar\r\n */\r\n create() {\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-toolbar';\r\n this.container.setAttribute('role', 'toolbar');\r\n this.container.setAttribute('aria-label', 'Formatting toolbar');\r\n\r\n // Create buttons from toolbarButtons array\r\n this.toolbarButtons.forEach(buttonConfig => {\r\n if (buttonConfig.name === 'separator') {\r\n const separator = this.createSeparator();\r\n this.container.appendChild(separator);\r\n } else {\r\n const button = this.createButton(buttonConfig);\r\n this.buttons[buttonConfig.name] = button;\r\n this.container.appendChild(button);\r\n }\r\n });\r\n\r\n // Insert toolbar before the wrapper (as sibling, not child)\r\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\r\n }\r\n\r\n /**\r\n * Create a toolbar separator\r\n */\r\n createSeparator() {\r\n const separator = document.createElement('div');\r\n separator.className = 'overtype-toolbar-separator';\r\n separator.setAttribute('role', 'separator');\r\n return separator;\r\n }\r\n\r\n /**\r\n * Create a toolbar button\r\n */\r\n createButton(buttonConfig) {\r\n const button = document.createElement('button');\r\n button.className = 'overtype-toolbar-button';\r\n button.type = 'button';\r\n button.setAttribute('data-button', buttonConfig.name);\r\n button.title = buttonConfig.title || '';\r\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\r\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\r\n\r\n // Special handling for viewMode dropdown\r\n if (buttonConfig.name === 'viewMode') {\r\n button.classList.add('has-dropdown');\r\n button.dataset.dropdown = 'true';\r\n button.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n this.toggleViewModeDropdown(button);\r\n });\r\n return button;\r\n }\r\n\r\n // Standard button click handler - delegate to performAction\r\n button._clickHandler = (e) => {\r\n e.preventDefault();\r\n const actionId = buttonConfig.actionId || buttonConfig.name;\r\n this.editor.performAction(actionId, e);\r\n };\r\n\r\n button.addEventListener('click', button._clickHandler);\r\n return button;\r\n }\r\n\r\n /**\r\n * Handle button action programmatically\r\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\r\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\r\n * @returns {Promise} Whether the action was executed\r\n */\r\n async handleAction(actionIdOrConfig) {\r\n // Old style: buttonConfig object with .action function - execute directly\r\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\r\n this.editor.textarea.focus();\r\n try {\r\n await actionIdOrConfig.action({\r\n editor: this.editor,\r\n getValue: () => this.editor.getValue(),\r\n setValue: (value) => this.editor.setValue(value),\r\n event: null\r\n });\r\n return true;\r\n } catch (error) {\r\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\r\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\r\n detail: { buttonName: actionIdOrConfig.name, error }\r\n }));\r\n return false;\r\n }\r\n }\r\n\r\n // New style: string actionId - delegate to performAction\r\n if (typeof actionIdOrConfig === 'string') {\r\n return this.editor.performAction(actionIdOrConfig, null);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Sanitize SVG to prevent XSS\r\n */\r\n sanitizeSVG(svg) {\r\n if (typeof svg !== 'string') return '';\r\n\r\n // Remove script tags and on* event handlers\r\n const cleaned = svg\r\n .replace(/)<[^<]*)*<\\/script>/gi, '')\r\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\r\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\r\n\r\n return cleaned;\r\n }\r\n\r\n /**\r\n * Toggle view mode dropdown (internal implementation)\r\n * Not exposed to users - viewMode button behavior is fixed\r\n */\r\n toggleViewModeDropdown(button) {\r\n // Close any existing dropdown\r\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\r\n if (existingDropdown) {\r\n existingDropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n return;\r\n }\r\n\r\n button.classList.add('dropdown-active');\r\n\r\n const dropdown = this.createViewModeDropdown(button);\r\n\r\n // Position dropdown relative to button\r\n const rect = button.getBoundingClientRect();\r\n dropdown.style.position = 'absolute';\r\n dropdown.style.top = `${rect.bottom + 5}px`;\r\n dropdown.style.left = `${rect.left}px`;\r\n\r\n document.body.appendChild(dropdown);\r\n\r\n // Click outside to close\r\n this.handleDocumentClick = (e) => {\r\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\r\n dropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n }\r\n };\r\n\r\n setTimeout(() => {\r\n document.addEventListener('click', this.handleDocumentClick);\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Create view mode dropdown menu (internal implementation)\r\n */\r\n createViewModeDropdown(button) {\r\n const dropdown = document.createElement('div');\r\n dropdown.className = 'overtype-dropdown-menu';\r\n\r\n const items = [\r\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\r\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\r\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\r\n ];\r\n\r\n const currentMode = this.editor.container.dataset.mode || 'normal';\r\n\r\n items.forEach(item => {\r\n const menuItem = document.createElement('button');\r\n menuItem.className = 'overtype-dropdown-item';\r\n menuItem.type = 'button';\r\n menuItem.textContent = item.label;\r\n\r\n if (item.id === currentMode) {\r\n menuItem.classList.add('active');\r\n menuItem.setAttribute('aria-current', 'true');\r\n const checkmark = document.createElement('span');\r\n checkmark.className = 'overtype-dropdown-icon';\r\n checkmark.textContent = item.icon;\r\n menuItem.prepend(checkmark);\r\n }\r\n\r\n menuItem.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n\r\n // Handle view mode changes\r\n switch(item.id) {\r\n case 'plain':\r\n this.editor.showPlainTextarea();\r\n break;\r\n case 'preview':\r\n this.editor.showPreviewMode();\r\n break;\r\n case 'normal':\r\n default:\r\n this.editor.showNormalEditMode();\r\n break;\r\n }\r\n\r\n dropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n });\r\n\r\n dropdown.appendChild(menuItem);\r\n });\r\n\r\n return dropdown;\r\n }\r\n\r\n /**\r\n * Update active states of toolbar buttons\r\n */\r\n updateButtonStates() {\r\n try {\r\n const activeFormats = markdownActions.getActiveFormats?.(\r\n this.editor.textarea,\r\n this.editor.textarea.selectionStart\r\n ) || [];\r\n\r\n Object.entries(this.buttons).forEach(([name, button]) => {\r\n if (name === 'viewMode') return; // Skip dropdown button\r\n\r\n let isActive = false;\r\n\r\n switch(name) {\r\n case 'bold':\r\n isActive = activeFormats.includes('bold');\r\n break;\r\n case 'italic':\r\n isActive = activeFormats.includes('italic');\r\n break;\r\n case 'code':\r\n isActive = false; // Disabled: unreliable in code blocks\r\n break;\r\n case 'bulletList':\r\n isActive = activeFormats.includes('bullet-list');\r\n break;\r\n case 'orderedList':\r\n isActive = activeFormats.includes('numbered-list');\r\n break;\r\n case 'taskList':\r\n isActive = activeFormats.includes('task-list');\r\n break;\r\n case 'quote':\r\n isActive = activeFormats.includes('quote');\r\n break;\r\n case 'h1':\r\n isActive = activeFormats.includes('header');\r\n break;\r\n case 'h2':\r\n isActive = activeFormats.includes('header-2');\r\n break;\r\n case 'h3':\r\n isActive = activeFormats.includes('header-3');\r\n break;\r\n }\r\n\r\n button.classList.toggle('active', isActive);\r\n button.setAttribute('aria-pressed', isActive.toString());\r\n });\r\n } catch (error) {\r\n // Silently fail if markdown-actions not available\r\n }\r\n }\r\n\r\n /**\r\n * Destroy toolbar and cleanup\r\n */\r\n destroy() {\r\n if (this.container) {\r\n // Clean up event listeners\r\n if (this.handleDocumentClick) {\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n }\r\n\r\n // Clean up button listeners\r\n Object.values(this.buttons).forEach(button => {\r\n if (button._clickHandler) {\r\n button.removeEventListener('click', button._clickHandler);\r\n delete button._clickHandler;\r\n }\r\n });\r\n\r\n // Remove container\r\n this.container.remove();\r\n this.container = null;\r\n this.buttons = {};\r\n }\r\n }\r\n}\r\n", "/**\r\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\r\n * Shows a clickable tooltip when cursor is within a link\r\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\r\n */\r\n\r\nexport class LinkTooltip {\r\n constructor(editor) {\r\n this.editor = editor;\r\n this.tooltip = null;\r\n this.currentLink = null;\r\n this.hideTimeout = null;\r\n this.visibilityChangeHandler = null;\r\n this.useFloatingUI = false;\r\n this.floatingUI = null;\r\n this.isTooltipHovered = false;\r\n\r\n this.init();\r\n }\r\n\r\n async init() {\r\n // Detect CSS anchor positioning support\r\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\r\n CSS.supports('position-area: center');\r\n\r\n // Load Floating UI if needed\r\n if (!supportsAnchorPositioning) {\r\n try {\r\n // Use indirect eval to prevent bundler from processing the import\r\n const importFn = new Function('url', 'return import(url)');\r\n const { computePosition, offset, shift, flip } = await importFn(\r\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\r\n );\r\n this.floatingUI = { computePosition, offset, shift, flip };\r\n this.useFloatingUI = true;\r\n } catch (error) {\r\n // If dynamic import fails, tooltips simply won't show\r\n console.warn('Failed to load Floating UI fallback:', error);\r\n this.floatingUI = null;\r\n this.useFloatingUI = false;\r\n }\r\n }\r\n\r\n // Create tooltip element\r\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\r\n this.createTooltip();\r\n\r\n // Listen for cursor position changes\r\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\r\n this.editor.textarea.addEventListener('keyup', e => {\r\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\r\n this.checkCursorPosition();\r\n }\r\n });\r\n\r\n // Hide tooltip when typing\r\n this.editor.textarea.addEventListener('input', () => this.hide());\r\n\r\n // Reposition or hide tooltip when scrolling\r\n this.editor.textarea.addEventListener('scroll', () => {\r\n if (this.useFloatingUI && this.currentLink) {\r\n // Reposition the tooltip for Floating UI\r\n this.showWithFloatingUI(this.currentLink);\r\n } else {\r\n // Hide for CSS anchor positioning (native browser behavior handles this)\r\n this.hide();\r\n }\r\n });\r\n\r\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\r\n this.editor.textarea.addEventListener('blur', () => {\r\n if (!this.isTooltipHovered) {\r\n this.hide();\r\n }\r\n });\r\n\r\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\r\n this.visibilityChangeHandler = () => {\r\n if (document.hidden) {\r\n this.hide();\r\n }\r\n };\r\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\r\n\r\n // Track hover state to prevent hiding when clicking tooltip\r\n this.tooltip.addEventListener('mouseenter', () => {\r\n this.isTooltipHovered = true;\r\n this.cancelHide();\r\n });\r\n this.tooltip.addEventListener('mouseleave', () => {\r\n this.isTooltipHovered = false;\r\n this.scheduleHide();\r\n });\r\n }\r\n\r\n createTooltip() {\r\n // Create tooltip element\r\n // Styles are now included in the main stylesheet (styles.js)\r\n this.tooltip = document.createElement('div');\r\n this.tooltip.className = 'overtype-link-tooltip';\r\n\r\n // Add link icon and text container\r\n this.tooltip.innerHTML = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n `;\r\n\r\n // Click handler to open link\r\n this.tooltip.addEventListener('click', e => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (this.currentLink) {\r\n window.open(this.currentLink.url, '_blank');\r\n this.hide();\r\n }\r\n });\r\n\r\n // Append tooltip to editor container\r\n this.editor.container.appendChild(this.tooltip);\r\n }\r\n\r\n checkCursorPosition() {\r\n const cursorPos = this.editor.textarea.selectionStart;\r\n const text = this.editor.textarea.value;\r\n\r\n // Find if cursor is within a markdown link\r\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\r\n\r\n if (linkInfo) {\r\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\r\n this.show(linkInfo);\r\n }\r\n } else {\r\n this.scheduleHide();\r\n }\r\n }\r\n\r\n findLinkAtPosition(text, position) {\r\n // Regex to find markdown links: [text](url)\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n let match;\r\n let linkIndex = 0;\r\n\r\n while ((match = linkRegex.exec(text)) !== null) {\r\n const start = match.index;\r\n const end = match.index + match[0].length;\r\n\r\n if (position >= start && position <= end) {\r\n return {\r\n text: match[1],\r\n url: match[2],\r\n index: linkIndex,\r\n start: start,\r\n end: end\r\n };\r\n }\r\n linkIndex++;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n show(linkInfo) {\r\n this.currentLink = linkInfo;\r\n this.cancelHide();\r\n\r\n // Update tooltip content\r\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\r\n urlSpan.textContent = linkInfo.url;\r\n\r\n if (this.useFloatingUI) {\r\n this.showWithFloatingUI(linkInfo);\r\n } else {\r\n this.showWithAnchorPositioning(linkInfo);\r\n }\r\n\r\n this.tooltip.classList.add('visible');\r\n }\r\n\r\n showWithAnchorPositioning(linkInfo) {\r\n // Set the CSS variable to point to the correct anchor\r\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\r\n }\r\n\r\n async showWithFloatingUI(linkInfo) {\r\n // Find the element in preview that corresponds to this link\r\n const anchorElement = this.findAnchorElement(linkInfo.index);\r\n\r\n if (!anchorElement) {\r\n return;\r\n }\r\n\r\n // Check if anchor element is visible and in viewport\r\n const rect = anchorElement.getBoundingClientRect();\r\n if (rect.width === 0 || rect.height === 0) {\r\n return;\r\n }\r\n\r\n try {\r\n // Compute position using Floating UI\r\n const { x, y } = await this.floatingUI.computePosition(\r\n anchorElement,\r\n this.tooltip,\r\n {\r\n placement: 'bottom',\r\n middleware: [\r\n this.floatingUI.offset(8),\r\n this.floatingUI.shift({ padding: 8 }),\r\n this.floatingUI.flip()\r\n ]\r\n }\r\n );\r\n\r\n // Apply position\r\n Object.assign(this.tooltip.style, {\r\n left: `${x}px`,\r\n top: `${y}px`,\r\n position: 'absolute'\r\n });\r\n } catch (error) {\r\n // If Floating UI computation fails, don't show tooltip\r\n console.warn('Floating UI positioning failed:', error);\r\n return;\r\n }\r\n }\r\n\r\n findAnchorElement(linkIndex) {\r\n // Find the element with the matching anchor-name style\r\n const preview = this.editor.preview;\r\n // Direct query for the specific link - more efficient than iterating\r\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\r\n }\r\n\r\n hide() {\r\n this.tooltip.classList.remove('visible');\r\n this.currentLink = null;\r\n this.isTooltipHovered = false;\r\n }\r\n\r\n scheduleHide() {\r\n this.cancelHide();\r\n this.hideTimeout = setTimeout(() => this.hide(), 300);\r\n }\r\n\r\n cancelHide() {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n this.hideTimeout = null;\r\n }\r\n }\r\n\r\n destroy() {\r\n this.cancelHide();\r\n\r\n // Remove visibility change listener\r\n if (this.visibilityChangeHandler) {\r\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\r\n this.visibilityChangeHandler = null;\r\n }\r\n\r\n if (this.tooltip && this.tooltip.parentNode) {\r\n this.tooltip.parentNode.removeChild(this.tooltip);\r\n }\r\n this.tooltip = null;\r\n this.currentLink = null;\r\n this.floatingUI = null;\r\n this.useFloatingUI = false;\r\n this.isTooltipHovered = false;\r\n }\r\n}\r\n", "/**\r\n * SVG icons for OverType toolbar\r\n * Quill-style icons with inline styles\r\n */\r\n\r\nexport const boldIcon = `\r\n \r\n \r\n`;\r\n\r\nexport const italicIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\nexport const h1Icon = `\r\n \r\n`;\r\n\r\nexport const h2Icon = `\r\n \r\n`;\r\n\r\nexport const h3Icon = `\r\n \r\n`;\r\n\r\nexport const linkIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\nexport const codeIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\n\r\nexport const bulletListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const orderedListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const quoteIcon = `\r\n \r\n \r\n`;\r\n\r\nexport const taskListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const eyeIcon = `\r\n \r\n \r\n`;", "/**\r\n * Toolbar button definitions for OverType editor\r\n * Export built-in buttons that can be used in custom toolbar configurations\r\n */\r\n\r\nimport * as icons from './icons.js';\r\nimport * as markdownActions from 'markdown-actions';\r\n\r\n/**\r\n * Built-in toolbar button definitions\r\n * Each button has: name, actionId, icon, title, action\r\n * - name: DOM identifier for the button element\r\n * - actionId: Canonical action identifier used by performAction\r\n * Action signature: ({ editor, getValue, setValue, event }) => void\r\n */\r\nexport const toolbarButtons = {\r\n bold: {\r\n name: 'bold',\r\n actionId: 'toggleBold',\r\n icon: icons.boldIcon,\r\n title: 'Bold (Ctrl+B)',\r\n action: ({ editor }) => {\r\n markdownActions.toggleBold(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n italic: {\r\n name: 'italic',\r\n actionId: 'toggleItalic',\r\n icon: icons.italicIcon,\r\n title: 'Italic (Ctrl+I)',\r\n action: ({ editor }) => {\r\n markdownActions.toggleItalic(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n code: {\r\n name: 'code',\r\n actionId: 'toggleCode',\r\n icon: icons.codeIcon,\r\n title: 'Inline Code',\r\n action: ({ editor }) => {\r\n markdownActions.toggleCode(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n separator: {\r\n name: 'separator'\r\n // No icon, title, or action - special separator element\r\n },\r\n\r\n link: {\r\n name: 'link',\r\n actionId: 'insertLink',\r\n icon: icons.linkIcon,\r\n title: 'Insert Link',\r\n action: ({ editor }) => {\r\n markdownActions.insertLink(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h1: {\r\n name: 'h1',\r\n actionId: 'toggleH1',\r\n icon: icons.h1Icon,\r\n title: 'Heading 1',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH1(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h2: {\r\n name: 'h2',\r\n actionId: 'toggleH2',\r\n icon: icons.h2Icon,\r\n title: 'Heading 2',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH2(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h3: {\r\n name: 'h3',\r\n actionId: 'toggleH3',\r\n icon: icons.h3Icon,\r\n title: 'Heading 3',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH3(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n bulletList: {\r\n name: 'bulletList',\r\n actionId: 'toggleBulletList',\r\n icon: icons.bulletListIcon,\r\n title: 'Bullet List',\r\n action: ({ editor }) => {\r\n markdownActions.toggleBulletList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n orderedList: {\r\n name: 'orderedList',\r\n actionId: 'toggleNumberedList',\r\n icon: icons.orderedListIcon,\r\n title: 'Numbered List',\r\n action: ({ editor }) => {\r\n markdownActions.toggleNumberedList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n taskList: {\r\n name: 'taskList',\r\n actionId: 'toggleTaskList',\r\n icon: icons.taskListIcon,\r\n title: 'Task List',\r\n action: ({ editor }) => {\r\n if (markdownActions.toggleTaskList) {\r\n markdownActions.toggleTaskList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n }\r\n },\r\n\r\n quote: {\r\n name: 'quote',\r\n actionId: 'toggleQuote',\r\n icon: icons.quoteIcon,\r\n title: 'Quote',\r\n action: ({ editor }) => {\r\n markdownActions.toggleQuote(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n viewMode: {\r\n name: 'viewMode',\r\n icon: icons.eyeIcon,\r\n title: 'View mode'\r\n // Special: handled internally by Toolbar class as dropdown\r\n // No action property - dropdown behavior is internal\r\n }\r\n};\r\n\r\n/**\r\n * Default toolbar button layout with separators\r\n * This is used when toolbar: true but no toolbarButtons provided\r\n */\r\nexport const defaultToolbarButtons = [\r\n toolbarButtons.bold,\r\n toolbarButtons.italic,\r\n toolbarButtons.code,\r\n toolbarButtons.separator,\r\n toolbarButtons.link,\r\n toolbarButtons.separator,\r\n toolbarButtons.h1,\r\n toolbarButtons.h2,\r\n toolbarButtons.h3,\r\n toolbarButtons.separator,\r\n toolbarButtons.bulletList,\r\n toolbarButtons.orderedList,\r\n toolbarButtons.taskList,\r\n toolbarButtons.separator,\r\n toolbarButtons.quote,\r\n toolbarButtons.separator,\r\n toolbarButtons.viewMode\r\n];\r\n"], + "mappings": "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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons", "themeName"] } diff --git a/dist/overtype.min.js b/dist/overtype.min.js index 96faf87..8507bd9 100644 --- a/dist/overtype.min.js +++ b/dist/overtype.min.js @@ -1,19 +1,19 @@ /** - * OverType v2.1.0 + * OverType v2.1.1 * A lightweight markdown editor library with perfect WYSIWYG alignment * @license MIT * @author David Miranda * https://github.com/panphora/overtype */ -var OverType=(()=>{var z=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var je=Object.getOwnPropertyNames;var ze=Object.prototype.hasOwnProperty;var Fe=(o,e,t)=>e in o?z(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Re=(o,e)=>{for(var t in e)z(o,t,{get:e[t],enumerable:!0})},Ve=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of je(e))!ze.call(o,i)&&i!==t&&z(o,i,{get:()=>e[i],enumerable:!(n=Oe(e,i))||n.enumerable});return o};var Ue=o=>Ve(z({},"__esModule",{value:!0}),o);var E=(o,e,t)=>(Fe(o,typeof e!="symbol"?e+"":e,t),t);var it={};Re(it,{OverType:()=>$,default:()=>ot,defaultToolbarButtons:()=>_,toolbarButtons:()=>k});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,n=>t[n])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,n,i)=>{let r=n.length;return`${n} ${i}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,n)=>`> ${n}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(n,i,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${i}
  • ${s}
  • `}else return`${i}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),n=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>n.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,n,i)=>{let r=`--link-${this.linkIndex++}`;return`
    [${n}](${i})`})}static identifyAndProtectSanctuaries(e){let t=new Map,n=0,i=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,u=h+a[2].length;r.push({start:h,end:u})}let p=new RegExp("(?c>=f.start&&h<=f.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((c,h)=>h.index-c.index),l.forEach(c=>{let h=`\uE000${n++}\uE001`;t.set(h,{type:"code",original:c.match,openTicks:c.openTicks,content:c.content,closeTicks:c.closeTicks}),i=i.substring(0,c.index)+h+i.substring(c.index+c.match.length)}),i=i.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(c,h,u)=>{let f=`\uE000${n++}\uE001`;return t.set(f,{type:"link",original:c,linkText:h,url:u}),f}),{protectedText:i,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((i,r)=>{let s=e.indexOf(i),a=e.indexOf(r);return s-a}).forEach(i=>{let r=t.get(i),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,c)=>{if(a.includes(c)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(c,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let p=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(i,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:n}=this.identifyAndProtectSanctuaries(e),i=t;return i=this.parseStrikethrough(i),i=this.parseBold(i),i=this.parseItalic(i),i=this.restoreAndTransformSanctuaries(i,n),i}static parseLine(e,t=!1){let n=this.escapeHtml(e);n=this.preserveIndentation(n,e);let i=this.parseHorizontalRule(n);if(i)return i;let r=this.parseCodeBlock(n);return r||(n=this.parseHeader(n),n=this.parseBlockquote(n),n=this.parseTaskList(n,t),n=this.parseBulletList(n),n=this.parseNumberedList(n),n=this.parseInlineElements(n),n.trim()===""?"
     
    ":`
    ${n}
    `)}static parse(e,t=-1,n=!1,i,r=!1){this.resetLinkIndex();let s=e.split(` -`),a=!1,d=s.map((l,c)=>{if(n&&c===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let u=this.escapeHtml(l);return`
    ${this.preserveIndentation(u,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,i)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let n=document.createElement("div");n.innerHTML=e;let i=null,r=null,s=null,a=!1,p=Array.from(n.children);for(let d=0;d0&&(s._codeContent+=` -`);let f=l.textContent.replace(/\u00A0/g," ");s._codeContent+=f,u.textContent.length>0&&(u.textContent+=` -`),u.textContent+=f,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let u=h.classList.contains("bullet-list"),f=h.classList.contains("ordered-list");if(!u&&!f){i=null,r=null;continue}let m=u?"ul":"ol";(!i||r!==m)&&(i=document.createElement(m),n.insertBefore(i,l),r=m);let g=[];for(let v of l.childNodes)if(v.nodeType===3&&v.textContent.match(/^\u00A0+$/))g.push(v.cloneNode(!0));else if(v===h)break;g.forEach(v=>{h.insertBefore(v,h.firstChild)}),i.appendChild(h),l.remove()}else i=null,r=null}return n.innerHTML}static postProcessHTMLManual(e,t){let n=e;n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(p=>{let d=p.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let c=d[1];return l[0].replace(/
    • /,`
    • ${c}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(p=>{let d=p.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let c=d[1];return l[0].replace(/
    2. /,`
    3. ${c}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let i=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return n=n.replace(i,(r,s,a,p)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(g=>g.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` -`),c=s.slice(3).trim(),h=c?` class="language-${c}"`:"",u=l,f=t||this.codeHighlighter;if(f)try{let g=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),v=f(g,c);v&&typeof v.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):v&&typeof v=="string"&&v.trim()&&(u=v)}catch(g){console.warn("Code highlighting failed:",g)}let m=`
    ${s}
    `;return m+=`
    ${u}
    `,m+=`
    ${p}
    `,m}),n}static getListContext(e,t){let n=e.split(` +var OverType=(()=>{var z=Object.defineProperty;var je=Object.getOwnPropertyDescriptor;var ze=Object.getOwnPropertyNames;var Fe=Object.prototype.hasOwnProperty;var Re=(o,e,t)=>e in o?z(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Ve=(o,e)=>{for(var t in e)z(o,t,{get:e[t],enumerable:!0})},Ue=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ze(e))!Fe.call(o,i)&&i!==t&&z(o,i,{get:()=>e[i],enumerable:!(n=je(e,i))||n.enumerable});return o};var De=o=>Ue(z({},"__esModule",{value:!0}),o);var T=(o,e,t)=>(Re(o,typeof e!="symbol"?e+"":e,t),t);var st={};Ve(st,{OverType:()=>I,default:()=>rt,defaultToolbarButtons:()=>_,toolbarButtons:()=>k});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,n=>t[n])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,n,i)=>{let r=n.length;return`${n} ${i}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,n)=>`> ${n}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(n,i,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${i}
  • ${s}
  • `}else return`${i}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),n=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>n.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,n,i)=>{let r=`--link-${this.linkIndex++}`;return`[${n}](${i})`})}static identifyAndProtectSanctuaries(e){let t=new Map,n=0,i=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,u=h+a[2].length;r.push({start:h,end:u})}let p=new RegExp("(?c>=v.start&&h<=v.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((c,h)=>h.index-c.index),l.forEach(c=>{let h=`\uE000${n++}\uE001`;t.set(h,{type:"code",original:c.match,openTicks:c.openTicks,content:c.content,closeTicks:c.closeTicks}),i=i.substring(0,c.index)+h+i.substring(c.index+c.match.length)}),i=i.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(c,h,u)=>{let v=`\uE000${n++}\uE001`;return t.set(v,{type:"link",original:c,linkText:h,url:u}),v}),{protectedText:i,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((i,r)=>{let s=e.indexOf(i),a=e.indexOf(r);return s-a}).forEach(i=>{let r=t.get(i),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,c)=>{if(a.includes(c)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(c,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let p=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(i,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:n}=this.identifyAndProtectSanctuaries(e),i=t;return i=this.parseStrikethrough(i),i=this.parseBold(i),i=this.parseItalic(i),i=this.restoreAndTransformSanctuaries(i,n),i}static parseLine(e,t=!1){let n=this.escapeHtml(e);n=this.preserveIndentation(n,e);let i=this.parseHorizontalRule(n);if(i)return i;let r=this.parseCodeBlock(n);return r||(n=this.parseHeader(n),n=this.parseBlockquote(n),n=this.parseTaskList(n,t),n=this.parseBulletList(n),n=this.parseNumberedList(n),n=this.parseInlineElements(n),n.trim()===""?"
     
    ":`
    ${n}
    `)}static parse(e,t=-1,n=!1,i,r=!1){this.resetLinkIndex();let s=e.split(` +`),a=!1,d=s.map((l,c)=>{if(n&&c===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let u=this.escapeHtml(l);return`
    ${this.preserveIndentation(u,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,i)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let n=document.createElement("div");n.innerHTML=e;let i=null,r=null,s=null,a=!1,p=Array.from(n.children);for(let d=0;d0&&(s._codeContent+=` +`);let v=l.textContent.replace(/\u00A0/g," ");s._codeContent+=v,u.textContent.length>0&&(u.textContent+=` +`),u.textContent+=v,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let u=h.classList.contains("bullet-list"),v=h.classList.contains("ordered-list");if(!u&&!v){i=null,r=null;continue}let f=u?"ul":"ol";(!i||r!==f)&&(i=document.createElement(f),n.insertBefore(i,l),r=f);let g=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))g.push(y.cloneNode(!0));else if(y===h)break;g.forEach(y=>{h.insertBefore(y,h.firstChild)}),i.appendChild(h),l.remove()}else i=null,r=null}return n.innerHTML}static postProcessHTMLManual(e,t){let n=e;n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(p=>{let d=p.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let c=d[1];return l[0].replace(/
    • /,`
    • ${c}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(p=>{let d=p.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let c=d[1];return l[0].replace(/
    2. /,`
    3. ${c}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let i=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return n=n.replace(i,(r,s,a,p)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(g=>g.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` +`),c=s.slice(3).trim(),h=c?` class="language-${c}"`:"",u=l,v=t||this.codeHighlighter;if(v)try{let g=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=v(g,c);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(u=y)}catch(g){console.warn("Code highlighting failed:",g)}let f=`
    ${s}
    `;return f+=`
    ${u}
    `,f+=`
    ${p}
    `,f}),n}static getListContext(e,t){let n=e.split(` `),i=0,r=0,s=0;for(let h=0;h=t){r=h,s=i;break}i+=u+1}let a=n[r],p=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:p,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:p,markerEndPos:s+l[1].length+l[2].length+1};let c=a.match(this.LIST_PATTERNS.numbered);return c?{inList:!0,listType:"numbered",indent:c[1],marker:parseInt(c[2]),content:c[3],lineStart:s,lineEnd:p,markerEndPos:s+c[1].length+c[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:p,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` `),n=new Map,i=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let p=a[1],d=p.length,l=a[3];i||n.clear();let c=(n.get(d)||0)+1;n.set(d,c);for(let[h]of n)h>d&&n.delete(h);return i=!0,`${p}${c}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(i=!1,n.clear()),s}).join(` -`)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var O=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.performAction(i,e),!0):!1}destroy(){}};var I={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},Q={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},X={solar:I,cave:Q,light:I,dark:Q};function P(o){return typeof o=="string"?{...X[o]||X.solar,name:o}:o}function N(o){let e=[];for(let[t,n]of Object.entries(o)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${n};`)}return e.join(` -`)}function Y(o,e={}){return{...o,colors:{...o.colors,...e}}}function ee(o={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:n='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:s={}}=o,a=Object.keys(s).length>0?` +`)}};T(S,"linkIndex",0),T(S,"codeHighlighter",null),T(S,"customSyntax",null),T(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var O=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.performAction(i,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},Y={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},qe={name:"auto",colors:A.colors},ee={solar:A,cave:Y,auto:qe,light:A,dark:Y};function M(o){return typeof o=="string"?{...ee[o]||ee.solar,name:o}:o}function W(o){return o!=="auto"?o:window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"cave":"solar"}function N(o){let e=[];for(let[t,n]of Object.entries(o)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${n};`)}return e.join(` +`)}function Q(o,e={}){return{...o,colors:{...o.colors,...e}}}function te(o={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:n='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:s={}}=o,a=Object.keys(s).length>0?` @media (max-width: 640px) { .overtype-wrapper .overtype-input, .overtype-wrapper .overtype-preview { @@ -861,28 +861,28 @@ var OverType=(()=>{var z=Object.defineProperty;var Oe=Object.getOwnPropertyDescr } ${a} - `}var De=Object.defineProperty,te=Object.getOwnPropertySymbols,qe=Object.prototype.hasOwnProperty,We=Object.prototype.propertyIsEnumerable,ne=(o,e,t)=>e in o?De(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,oe=(o,e)=>{for(var t in e||(e={}))qe.call(e,t)&&ne(o,t,e[t]);if(te)for(var t of te(e))We.call(e,t)&&ne(o,t,e[t]);return o},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Ke(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function H(o){return oe(oe({},Ke()),o)}var R=!1;function Ze(){return R}function y(o,e,t){R&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function F(o,e){if(!R)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function ae(o){R&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var A=null;function B(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Ze();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),p=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(p.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(A===null||A===!0){o.contentEditable="true";try{A=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",A,"for text with",e.split(` -`).length,"lines")}catch(c){A=!1,i&&console.log("execCommand threw error:",c)}o.contentEditable="false"}if(i&&(console.log("canInsertText before:",A),console.log("execCommand result:",A)),A){let c=a+e+p,h=o.value;i&&(console.log("Expected length:",c.length),console.log("Actual length:",h.length)),h!==c&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(c.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!A)if(i&&console.log("Using manual insertion"),o.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(c){}o.value=a+e+p;try{document.execCommand("ms-endUndoUnit")}catch(c){}o.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,n),t!=null&&n!=null?o.setSelectionRange(t,n):o.setSelectionRange(r,o.selectionEnd),i&&(console.log("Final value length:",o.value.length),console.groupEnd())}function ie(o){return o.trim().split(` -`).length>1}function Je(o,e){let t=e;for(;o[t]&&o[t-1]!=null&&!o[t-1].match(/\s/);)t--;return t}function Ge(o,e,t){let n=e,i=t?/\n/:/\s/;for(;o[n]&&!o[n].match(i);)n++;return n}function le(o){let e=o.value.split(` -`),t=0;for(let n=0;n=t&&o.selectionStart=t&&o.selectionEnde in o?We(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,ie=(o,e)=>{for(var t in e||(e={}))Qe.call(e,t)&&oe(o,t,e[t]);if(ne)for(var t of ne(e))Ke.call(e,t)&&oe(o,t,e[t]);return o},E={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Ge(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return ie(ie({},Ge()),o)}var R=!1;function Ze(){return R}function b(o,e,t){R&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function F(o,e){if(!R)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function le(o){R&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function B(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Ze();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),p=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(p.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` +`).length,"lines")}catch(c){H=!1,i&&console.log("execCommand threw error:",c)}o.contentEditable="false"}if(i&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let c=a+e+p,h=o.value;i&&(console.log("Expected length:",c.length),console.log("Actual length:",h.length)),h!==c&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(c.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!H)if(i&&console.log("Using manual insertion"),o.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(c){}o.value=a+e+p;try{document.execCommand("ms-endUndoUnit")}catch(c){}o.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,n),t!=null&&n!=null?o.setSelectionRange(t,n):o.setSelectionRange(r,o.selectionEnd),i&&(console.log("Final value length:",o.value.length),console.groupEnd())}function re(o){return o.trim().split(` +`).length>1}function Je(o,e){let t=e;for(;o[t]&&o[t-1]!=null&&!o[t-1].match(/\s/);)t--;return t}function Xe(o,e,t){let n=e,i=t?/\n/:/\s/;for(;o[n]&&!o[n].match(i);)n++;return n}function ce(o){let e=o.value.split(` +`),t=0;for(let n=0;n=t&&o.selectionStart=t&&o.selectionEnd0&&s[a-1]!==` `;)a--;if(r){let d=n;for(;d0?`${s} -`:i,v=ie(m)&&a&&a.length>0?` -${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(g=` ${g}`)}m=Qe(o,g,v,e.multiline);let b=o.selectionStart,x=o.selectionEnd,M=p&&p.length>0&&v.indexOf(p)>-1&&m.length>0;if(c){let L=W(o);t=L.newlinesToAppend,n=L.newlinesToPrepend,g=t+i,v+=n}if(m.startsWith(g)&&m.endsWith(v)){let L=m.slice(g.length,m.length-v.length);if(u===f){let C=u-g.length;C=Math.max(C,b),C=Math.min(C,b+L.length),b=x=C}else x=b+L.length;return{text:L,selectionStart:b,selectionEnd:x}}else if(M)if(l&&l.length>0&&m.match(l)){v=v.replace(p,m);let L=g+v;return b=x=b+g.length,{text:L,selectionStart:b,selectionEnd:x}}else{let L=g+m+v;return b=b+g.length+m.length+v.indexOf(p),x=b+p.length,{text:L,selectionStart:b,selectionEnd:x}}else{let L=g+m+v;b=u+g.length,x=f+g.length;let C=m.match(/^\s*|\s*$/g);if(h&&C){let J=C[0]||"",G=C[1]||"";L=J+g+m.trim()+v+G,b+=J.length,x-=G.length}return{text:L,selectionStart:b,selectionEnd:x}}}function ce(o,e){let{prefix:t,suffix:n,surroundWithNewlines:i}=e,r=o.value.slice(o.selectionStart,o.selectionEnd),s=o.selectionStart,a=o.selectionEnd,p=r.split(` +`;)d++;o.selectionStart=a,o.selectionEnd=d}else ce(o);let p=e(o);if(t.adjustSelection){let l=o.value.slice(o.selectionStart,o.selectionEnd).startsWith(t.prefix),c=t.adjustSelection(l,n,i,a);p.selectionStart=c.start,p.selectionEnd=c.end}else if(t.prefix){let l=o.value.slice(o.selectionStart,o.selectionEnd).startsWith(t.prefix);r?l?(p.selectionStart=Math.max(n-t.prefix.length,a),p.selectionEnd=p.selectionStart):(p.selectionStart=n+t.prefix.length,p.selectionEnd=p.selectionStart):l?(p.selectionStart=Math.max(n-t.prefix.length,a),p.selectionEnd=Math.max(i-t.prefix.length,a)):(p.selectionStart=n+t.prefix.length,p.selectionEnd=i+t.prefix.length)}return p}function U(o,e){let t,n,{prefix:i,suffix:r,blockPrefix:s,blockSuffix:a,replaceNext:p,prefixSpace:d,scanFor:l,surroundWithNewlines:c,trimFirst:h}=e,u=o.selectionStart,v=o.selectionEnd,f=o.value.slice(o.selectionStart,o.selectionEnd),g=re(f)&&s&&s.length>0?`${s} +`:i,y=re(f)&&a&&a.length>0?` +${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(g=` ${g}`)}f=Ye(o,g,y,e.multiline);let w=o.selectionStart,x=o.selectionEnd,P=p&&p.length>0&&y.indexOf(p)>-1&&f.length>0;if(c){let L=K(o);t=L.newlinesToAppend,n=L.newlinesToPrepend,g=t+i,y+=n}if(f.startsWith(g)&&f.endsWith(y)){let L=f.slice(g.length,f.length-y.length);if(u===v){let C=u-g.length;C=Math.max(C,w),C=Math.min(C,w+L.length),w=x=C}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if(P)if(l&&l.length>0&&f.match(l)){y=y.replace(p,f);let L=g+y;return w=x=w+g.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=g+f+y;return w=w+g.length+f.length+y.indexOf(p),x=w+p.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=g+f+y;w=u+g.length,x=v+g.length;let C=f.match(/^\s*|\s*$/g);if(h&&C){let J=C[0]||"",X=C[1]||"";L=J+g+f.trim()+y+X,w+=J.length,x-=X.length}return{text:L,selectionStart:w,selectionEnd:x}}}function pe(o,e){let{prefix:t,suffix:n,surroundWithNewlines:i}=e,r=o.value.slice(o.selectionStart,o.selectionEnd),s=o.selectionStart,a=o.selectionEnd,p=r.split(` `);if(p.every(l=>l.startsWith(t)&&(!n||l.endsWith(n))))r=p.map(l=>{let c=l.slice(t.length);return n&&(c=c.slice(0,c.length-n.length)),c}).join(` `),a=s+r.length;else if(r=p.map(l=>t+l+(n||"")).join(` -`),i){let{newlinesToAppend:l,newlinesToPrepend:c}=W(o);s+=l.length,a=s+r.length,r=l+r+c}return{text:r,selectionStart:s,selectionEnd:a}}function re(o){let e=o.split(` +`),i){let{newlinesToAppend:l,newlinesToPrepend:c}=K(o);s+=l.length,a=s+r.length,r=l+r+c}return{text:r,selectionStart:s,selectionEnd:a}}function se(o){let e=o.split(` `),t=/^\d+\.\s+/,n=e.every(r=>t.test(r)),i=e;return n&&(i=e.map(r=>r.replace(t,""))),{text:i.join(` -`),processed:n}}function se(o){let e=o.split(` +`),processed:n}}function ae(o){let e=o.split(` `),t="- ",n=e.every(r=>r.startsWith(t)),i=e;return n&&(i=e.map(r=>r.slice(t.length))),{text:i.join(` -`),processed:n}}function j(o,e){return e?"- ":`${o+1}. `}function Xe(o,e){let t,n,i;return o.orderedList?(t=re(e),n=se(t.text),i=n.text):(t=se(e),n=re(t.text),i=n.text),[t,n,i]}function Ye(o,e){let t=o.selectionStart===o.selectionEnd,n=o.selectionStart,i=o.selectionEnd;le(o);let r=o.value.slice(o.selectionStart,o.selectionEnd),[s,a,p]=Xe(e,r),d=p.split(` -`).map((m,g)=>`${j(g,e.unorderedList)}${m}`),l=d.reduce((m,g,v)=>m+j(v,e.unorderedList).length,0),c=d.reduce((m,g,v)=>m+j(v,!e.unorderedList).length,0);if(s.processed)return t?(n=Math.max(n-j(0,e.unorderedList).length,0),i=n):(n=o.selectionStart,i=o.selectionEnd-l),{text:p,selectionStart:n,selectionEnd:i};let{newlinesToAppend:h,newlinesToPrepend:u}=W(o),f=h+d.join(` -`)+u;return t?(n=Math.max(n+j(0,e.unorderedList).length+h.length,0),i=n):a.processed?(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l-c):(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l),{text:f,selectionStart:n,selectionEnd:i}}function pe(o,e){let t=V(o,n=>Ye(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),p=/^\d+\.\s+/,d=/^- /,l=p.test(a),c=d.test(a),h=e.orderedList&&l||e.unorderedList&&c;if(i===r)if(h){let u=a.match(e.orderedList?p:d),f=u?u[0].length:0;return{start:Math.max(i-f,s),end:Math.max(i-f,s)}}else if(l||c){let u=a.match(l?p:d),f=u?u[0].length:0,g=(e.unorderedList?2:3)-f;return{start:i+g,end:i+g}}else{let u=e.unorderedList?2:3;return{start:i+u,end:i+u}}else if(h){let u=a.match(e.orderedList?p:d),f=u?u[0].length:0;return{start:Math.max(i-f,s),end:Math.max(r-f,s)}}else if(l||c){let u=a.match(l?p:d),f=u?u[0].length:0,g=(e.unorderedList?2:3)-f;return{start:i+g,end:r+g}}else{let u=e.unorderedList?2:3;return{start:i+u,end:r+u}}}});B(o,t)}function et(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` -`),s=0,a="";for(let c of r){if(t>=s&&t<=s+c.length){a=c;break}s+=c.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let p=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(p,d);if(l.includes("**")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("**"),f=h.indexOf("**");u!==-1&&f!==-1&&e.push("bold")}if(l.includes("_")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("_"),f=h.indexOf("_");u!==-1&&f!==-1&&e.push("italic")}if(l.includes("`")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100));c.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("["),f=h.indexOf("]");u!==-1&&f!==-1&&i.slice(n+f+1,n+f+10).startsWith("(")&&e.push("link")}return e}function de(o){if(!o||o.disabled||o.readOnly)return;y("toggleBold","Starting"),F(o,"Before");let e=H(T.bold),t=U(o,e);ae(t),B(o,t),F(o,"After")}function he(o){if(!o||o.disabled||o.readOnly)return;let e=H(T.italic),t=U(o,e);B(o,t)}function ue(o){if(!o||o.disabled||o.readOnly)return;let e=H(T.code),t=U(o,e);B(o,t)}function me(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=H(T.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);B(o,r)}function fe(o){if(!o||o.disabled||o.readOnly)return;let e=H(T.bulletList);pe(o,e)}function ge(o){if(!o||o.disabled||o.readOnly)return;let e=H(T.numberedList);pe(o,e)}function ve(o){if(!o||o.disabled||o.readOnly)return;y("toggleQuote","Starting"),F(o,"Initial");let e=H(T.quote),t=V(o,n=>ce(n,e),{prefix:e.prefix});ae(t),B(o,t),F(o,"Final")}function K(o){if(!o||o.disabled||o.readOnly)return;let e=H(T.taskList),t=V(o,n=>ce(n,e),{prefix:e.prefix});B(o,t)}function Z(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),y("insertHeader","============ START ============"),y("insertHeader",`Level: ${e}, Toggle: ${t}`),y("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=H(T[n]||T.header1);y("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,p=s;for(;p>0&&r[p-1]!==` +`),processed:n}}function j(o,e){return e?"- ":`${o+1}. `}function et(o,e){let t,n,i;return o.orderedList?(t=se(e),n=ae(t.text),i=n.text):(t=ae(e),n=se(t.text),i=n.text),[t,n,i]}function tt(o,e){let t=o.selectionStart===o.selectionEnd,n=o.selectionStart,i=o.selectionEnd;ce(o);let r=o.value.slice(o.selectionStart,o.selectionEnd),[s,a,p]=et(e,r),d=p.split(` +`).map((f,g)=>`${j(g,e.unorderedList)}${f}`),l=d.reduce((f,g,y)=>f+j(y,e.unorderedList).length,0),c=d.reduce((f,g,y)=>f+j(y,!e.unorderedList).length,0);if(s.processed)return t?(n=Math.max(n-j(0,e.unorderedList).length,0),i=n):(n=o.selectionStart,i=o.selectionEnd-l),{text:p,selectionStart:n,selectionEnd:i};let{newlinesToAppend:h,newlinesToPrepend:u}=K(o),v=h+d.join(` +`)+u;return t?(n=Math.max(n+j(0,e.unorderedList).length+h.length,0),i=n):a.processed?(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l-c):(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l),{text:v,selectionStart:n,selectionEnd:i}}function de(o,e){let t=V(o,n=>tt(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),p=/^\d+\.\s+/,d=/^- /,l=p.test(a),c=d.test(a),h=e.orderedList&&l||e.unorderedList&&c;if(i===r)if(h){let u=a.match(e.orderedList?p:d),v=u?u[0].length:0;return{start:Math.max(i-v,s),end:Math.max(i-v,s)}}else if(l||c){let u=a.match(l?p:d),v=u?u[0].length:0,g=(e.unorderedList?2:3)-v;return{start:i+g,end:i+g}}else{let u=e.unorderedList?2:3;return{start:i+u,end:i+u}}else if(h){let u=a.match(e.orderedList?p:d),v=u?u[0].length:0;return{start:Math.max(i-v,s),end:Math.max(r-v,s)}}else if(l||c){let u=a.match(l?p:d),v=u?u[0].length:0,g=(e.unorderedList?2:3)-v;return{start:i+g,end:r+g}}else{let u=e.unorderedList?2:3;return{start:i+u,end:r+u}}}});B(o,t)}function nt(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` +`),s=0,a="";for(let c of r){if(t>=s&&t<=s+c.length){a=c;break}s+=c.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let p=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(p,d);if(l.includes("**")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("**"),v=h.indexOf("**");u!==-1&&v!==-1&&e.push("bold")}if(l.includes("_")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("_"),v=h.indexOf("_");u!==-1&&v!==-1&&e.push("italic")}if(l.includes("`")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100));c.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("["),v=h.indexOf("]");u!==-1&&v!==-1&&i.slice(n+v+1,n+v+10).startsWith("(")&&e.push("link")}return e}function he(o){if(!o||o.disabled||o.readOnly)return;b("toggleBold","Starting"),F(o,"Before");let e=$(E.bold),t=U(o,e);le(t),B(o,t),F(o,"After")}function ue(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.italic),t=U(o,e);B(o,t)}function me(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.code),t=U(o,e);B(o,t)}function fe(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=$(E.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);B(o,r)}function ve(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.bulletList);de(o,e)}function ge(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.numberedList);de(o,e)}function ye(o){if(!o||o.disabled||o.readOnly)return;b("toggleQuote","Starting"),F(o,"Initial");let e=$(E.quote),t=V(o,n=>pe(n,e),{prefix:e.prefix});le(t),B(o,t),F(o,"Final")}function G(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.taskList),t=V(o,n=>pe(n,e),{prefix:e.prefix});B(o,t)}function Z(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=$(E[n]||E.header1);b("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,p=s;for(;p>0&&r[p-1]!==` `;)p--;let d=a;for(;d{let v=g.value.slice(g.selectionStart,g.selectionEnd);y("insertHeader",`Line in operation: "${v}"`);let b=v.replace(/^#{1,6}\s*/,"");y("insertHeader",`Cleaned line: "${b}"`);let x;return f?(y("insertHeader","ACTION: Toggling OFF - removing header"),x=b):h>0?(y("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=i.prefix+b):(y("insertHeader","ACTION: Adding new header"),x=i.prefix+b),y("insertHeader",`New line: "${x}"`),{text:x,selectionStart:g.selectionStart,selectionEnd:g.selectionEnd}},{prefix:i.prefix,adjustSelection:(g,v,b,x)=>{if(y("insertHeader","Adjusting selection:"),y("insertHeader",` - isRemoving param: ${g}`),y("insertHeader",` - shouldToggleOff: ${f}`),y("insertHeader",` - selStart: ${v}, selEnd: ${b}`),y("insertHeader",` - lineStartPos: ${x}`),f){let M=Math.max(v-u,x);return y("insertHeader",` - Removing header, adjusting by -${u}`),{start:M,end:v===b?M:Math.max(b-u,x)}}else if(u>0){let M=i.prefix.length-u;return y("insertHeader",` - Replacing header, adjusting by ${M}`),{start:v+M,end:b+M}}else return y("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:v+i.prefix.length,end:b+i.prefix.length}}});y("insertHeader",`Final result: text="${m.text}", cursor=${m.selectionStart}-${m.selectionEnd}`),y("insertHeader","============ END ============"),B(o,m)}function ye(o){Z(o,1,!0)}function be(o){Z(o,2,!0)}function we(o){Z(o,3,!0)}function xe(o){return et(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=xe)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var q=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` +`;)d++;let l=r.slice(p,d);b("insertHeader",`Current line (before): "${l}"`);let c=l.match(/^(#{1,6})\s*/),h=c?c[1].length:0,u=c?c[0].length:0;b("insertHeader","Existing header check:"),b("insertHeader",` - Match: ${c?`"${c[0]}"`:"none"}`),b("insertHeader",` - Existing level: ${h}`),b("insertHeader",` - Existing prefix length: ${u}`),b("insertHeader",` - Target level: ${e}`);let v=t&&h===e;b("insertHeader",`Should toggle OFF: ${v} (toggle=${t}, existingLevel=${h}, level=${e})`);let f=V(o,g=>{let y=g.value.slice(g.selectionStart,g.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return v?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):h>0?(b("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=i.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=i.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:g.selectionStart,selectionEnd:g.selectionEnd}},{prefix:i.prefix,adjustSelection:(g,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${g}`),b("insertHeader",` - shouldToggleOff: ${v}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),v){let P=Math.max(y-u,x);return b("insertHeader",` - Removing header, adjusting by -${u}`),{start:P,end:y===w?P:Math.max(w-u,x)}}else if(u>0){let P=i.prefix.length-u;return b("insertHeader",` - Replacing header, adjusting by ${P}`),{start:y+P,end:w+P}}else return b("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:y+i.prefix.length,end:w+i.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),B(o,f)}function be(o){Z(o,1,!0)}function we(o){Z(o,2,!0)}function xe(o){Z(o,3,!0)}function ke(o){return nt(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=ke)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var q=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` @@ -890,20 +890,20 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! - `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,n=this.findLinkAtPosition(t,e);n?(!this.currentLink||this.currentLink.url!==n.url||this.currentLink.index!==n.index)&&this.show(n):this.scheduleHide()}findLinkAtPosition(e,t){let n=/\[([^\]]+)\]\(([^)]+)\)/g,i,r=0;for(;(i=n.exec(e))!==null;){let s=i.index,a=i.index+i[0].length;if(t>=s&&t<=a)return{text:i[1],url:i[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let n=t.getBoundingClientRect();if(!(n.width===0||n.height===0))try{let{x:i,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${i}px`,top:`${r}px`,position:"absolute"})}catch(i){console.warn("Floating UI positioning failed:",i);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Le=` + `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,n=this.findLinkAtPosition(t,e);n?(!this.currentLink||this.currentLink.url!==n.url||this.currentLink.index!==n.index)&&this.show(n):this.scheduleHide()}findLinkAtPosition(e,t){let n=/\[([^\]]+)\]\(([^)]+)\)/g,i,r=0;for(;(i=n.exec(e))!==null;){let s=i.index,a=i.index+i[0].length;if(t>=s&&t<=a)return{text:i[1],url:i[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let n=t.getBoundingClientRect();if(!(n.width===0||n.height===0))try{let{x:i,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${i}px`,top:`${r}px`,position:"absolute"})}catch(i){console.warn("Floating UI positioning failed:",i);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Se=` -`,Se=` +`,Te=` `,Ee=` -`,Te=` - `,Ce=` - + `,Ae=` + +`,Me=` @@ -918,7 +918,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! -`,Me=` +`,Ie=` @@ -926,7 +926,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! -`,Ie=` +`,Pe=` `,Be=` @@ -936,10 +936,10 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! -`,Pe=` +`,Ne=` -`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Le,title:"Bold (Ctrl+B)",action:({editor:o})=>{de(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Se,title:"Italic (Ctrl+I)",action:({editor:o})=>{he(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:He,title:"Inline Code",action:({editor:o})=>{ue(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:Ae,title:"Insert Link",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ee,title:"Heading 1",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Te,title:"Heading 2",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Ce,title:"Heading 3",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Me,title:"Numbered List",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:Be,title:"Task List",action:({editor:o})=>{K&&(K(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Ie,title:"Quote",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Pe,title:"View mode"}},_=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function Ne(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function _e(o){let e=o||_;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function nt(o,e){let t=_e(o),n=_e(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(w.prototype);return s._init(r,t),r.overTypeInstance=s,w.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.options=this._mergeOptions(t),this.instanceId=++w.instanceCount,this.initialized=!1,w.injectStyles(),w.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.shortcuts=new O(this),this._rebuildActionsMap(),this.linkTooltip=new q(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||w.currentTheme||I,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?P(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=N(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||w.currentTheme||I,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?P(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=N(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||_;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=Ne(_),this.options.toolbarButtons&&Object.assign(this.actionsById,Ne(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;t`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Se,title:"Bold (Ctrl+B)",action:({editor:o})=>{he(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{ue(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:He,title:"Inline Code",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:Me,title:"Insert Link",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ee,title:"Heading 1",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ce,title:"Heading 2",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Ae,title:"Heading 3",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Ie,title:"Numbered List",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:Be,title:"Task List",action:({editor:o})=>{G&&(G(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},_=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function _e(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function Oe(o){let e=o||_;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function it(o,e){let t=Oe(o),n=Oe(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(m.prototype);return s._init(r,t),r.overTypeInstance=s,m.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++m.instanceCount,this.initialized=!1,m.injectStyles(),m.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new O(this),this._rebuildActionsMap(),this.linkTooltip=new q(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||m.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=N(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||m.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=N(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||_;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=_e(_),this.options.toolbarButtons&&Object.assign(this.actionsById,_e(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tc.replace(/^ /,"")).join(` `);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+p,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else if(n!==i){let s=r.substring(0,n),a=r.substring(n,i),p=r.substring(i),l=a.split(` @@ -948,7 +948,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! `+t),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}splitListItem(e,t){let n=e.content.substring(t-e.markerEndPos);this.textarea.setSelectionRange(t,e.lineEnd),document.execCommand("delete");let i=S.createNewListItem(e);document.execCommand("insertText",!1,` `+i+n);let r=this.textarea.selectionStart-n.length;this.textarea.setSelectionRange(r,r),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}scheduleNumberedListUpdate(){this.numberUpdateTimeout&&clearTimeout(this.numberUpdateTimeout),this.numberUpdateTimeout=setTimeout(()=>{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,n=S.renumberLists(e);if(n!==e){let i=0,r=e.split(` `),s=n.split(` -`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&nt(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){this.instanceTheme=e;let t=typeof e=="string"?P(e):e,n=typeof t=="string"?t:t.name;if(n&&this.container.setAttribute("data-theme",n),t&&t.colors){let i=N(t.colors);this.container.style.cssText+=i}return this.updatePreview(),this}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` +`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&it(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAutoThemeListener(),this.instanceTheme=e,e==="auto"){this._setupAutoThemeListener();let t=W("auto");this._applyResolvedTheme(t)}else{let t=typeof e=="string"?M(e):e,n=typeof t=="string"?t:t.name;if(n&&this.container.setAttribute("data-theme",n),t&&t.colors){let i=N(t.colors);this.container.style.cssText+=i}this.updatePreview()}return this}_applyResolvedTheme(e){let t=M(e);if(this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t&&t.colors){let n=N(t.colors);this.container.style.cssText+=n}this.updatePreview()}_setupAutoThemeListener(){window.matchMedia&&(this.autoThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.autoThemeListener=e=>{let t=e.matches?"cave":"solar";this._applyResolvedTheme(t)},this.autoThemeMediaQuery.addEventListener?this.autoThemeMediaQuery.addEventListener("change",this.autoThemeListener):this.autoThemeMediaQuery.addListener&&this.autoThemeMediaQuery.addListener(this.autoThemeListener))}_cleanupAutoThemeListener(){this.autoThemeMediaQuery&&this.autoThemeListener&&(this.autoThemeMediaQuery.removeEventListener?this.autoThemeMediaQuery.removeEventListener("change",this.autoThemeListener):this.autoThemeMediaQuery.removeListener&&this.autoThemeMediaQuery.removeListener(this.autoThemeListener),this.autoThemeMediaQuery=null,this.autoThemeListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` `),n=e.length,i=e.split(/\s+/).filter(l=>l.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(` `),p=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:n,words:i,lines:t.length,line:p,column:d}):this.statsBar.innerHTML=`
    @@ -956,7 +956,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! ${n} chars, ${i} words, ${t.length} lines
    Line ${p}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let p=e.scrollHeight;if(this.options.minHeight){let c=parseInt(this.options.minHeight);p=Math.max(p,c)}let d="hidden";if(this.options.maxHeight){let c=parseInt(this.options.maxHeight);p>c&&(p=c,d="auto")}let l=p+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==p&&(this.previousHeight=p)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this.element.overTypeInstance=null,w.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new w(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let p=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[p]=w._parseDataValue(s.value)}return new w(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||w.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=w.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(w.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=w.currentTheme||I,i=ee({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),w.stylesInjected=!0}static setTheme(e,t=null){let n=typeof e=="string"?P(e):e;t&&(n=Y(n,t)),w.currentTheme=n,w.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(r=>{let s=typeof n=="string"?n:n.name;s&&r.setAttribute("data-theme",s)}),document.querySelectorAll(".overtype-wrapper").forEach(r=>{if(!r.closest(".overtype-container")){let a=typeof n=="string"?n:n.name;a&&r.setAttribute("data-theme",a)}let s=r._instance;s&&s.updatePreview()});let i=typeof n=="string"?n:n.name;document.querySelectorAll("overtype-editor").forEach(r=>{i&&typeof r.setAttribute=="function"&&r.setAttribute("theme",i),typeof r.refreshTheme=="function"&&r.refreshTheme()})}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){w.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),w.globalListenersInitialized=!0)}};E(w,"instances",new WeakMap),E(w,"stylesInjected",!1),E(w,"globalListenersInitialized",!1),E(w,"instanceCount",0);var $=w;$.MarkdownParser=S;$.ShortcutsManager=O;$.themes={solar:I,cave:P("cave")};$.getTheme=P;$.currentTheme=I;var ot=$;return Ue(it);})(); + `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let p=e.scrollHeight;if(this.options.minHeight){let c=parseInt(this.options.minHeight);p=Math.max(p,c)}let d="hidden";if(this.options.maxHeight){let c=parseInt(this.options.maxHeight);p>c&&(p=c,d="auto")}let l=p+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==p&&(this.previousHeight=p)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAutoThemeListener(),this.element.overTypeInstance=null,m.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new m(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let p=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[p]=m._parseDataValue(s.value)}return new m(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||m.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=m.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(m.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=m.currentTheme||A,i=te({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),m.stylesInjected=!0}static setTheme(e,t=null){if(m._cleanupGlobalAutoThemeListener(),e==="auto"){m._setupGlobalAutoThemeListener();let n=W("auto");m._applyGlobalResolvedTheme(n,t)}else{let n=typeof e=="string"?M(e):e;t&&(n=Q(n,t)),m.currentTheme=n,m.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(r=>{let s=typeof n=="string"?n:n.name;s&&r.setAttribute("data-theme",s)}),document.querySelectorAll(".overtype-wrapper").forEach(r=>{if(!r.closest(".overtype-container")){let a=typeof n=="string"?n:n.name;a&&r.setAttribute("data-theme",a)}let s=r._instance;s&&s.updatePreview()});let i=typeof n=="string"?n:n.name;document.querySelectorAll("overtype-editor").forEach(r=>{i&&typeof r.setAttribute=="function"&&r.setAttribute("theme",i),typeof r.refreshTheme=="function"&&r.refreshTheme()})}}static _applyGlobalResolvedTheme(e,t=null){let n=M(e);t&&(n=Q(n,t)),m.currentTheme=n,m.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(i=>{i.setAttribute("data-theme","auto"),i.setAttribute("data-resolved-theme",e)}),document.querySelectorAll(".overtype-wrapper").forEach(i=>{i.closest(".overtype-container")||(i.setAttribute("data-theme","auto"),i.setAttribute("data-resolved-theme",e));let r=i._instance;r&&r.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(i=>{typeof i.setAttribute=="function"&&(i.setAttribute("theme","auto"),i.setAttribute("data-resolved-theme",e)),typeof i.refreshTheme=="function"&&i.refreshTheme()})}static _setupGlobalAutoThemeListener(){window.matchMedia&&(m.autoThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),m.autoThemeListener=e=>{let t=e.matches?"cave":"solar";m._applyGlobalResolvedTheme(t)},m.autoThemeMediaQuery.addEventListener?m.autoThemeMediaQuery.addEventListener("change",m.autoThemeListener):m.autoThemeMediaQuery.addListener&&m.autoThemeMediaQuery.addListener(m.autoThemeListener))}static _cleanupGlobalAutoThemeListener(){m.autoThemeMediaQuery&&m.autoThemeListener&&(m.autoThemeMediaQuery.removeEventListener?m.autoThemeMediaQuery.removeEventListener("change",m.autoThemeListener):m.autoThemeMediaQuery.removeListener&&m.autoThemeMediaQuery.removeListener(m.autoThemeListener),m.autoThemeMediaQuery=null,m.autoThemeListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){m.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),m.globalListenersInitialized=!0)}};T(m,"instances",new WeakMap),T(m,"stylesInjected",!1),T(m,"globalListenersInitialized",!1),T(m,"instanceCount",0),T(m,"autoThemeMediaQuery",null),T(m,"autoThemeListener",null);var I=m;I.MarkdownParser=S;I.ShortcutsManager=O;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var rt=I;return De(st);})(); /** * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment * @version 1.0.0 diff --git a/package-lock.json b/package-lock.json index 2409471..1ed62d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -156,6 +156,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -179,6 +180,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } diff --git a/src/overtype.js b/src/overtype.js index 4dd83fc..d43f28e 100644 --- a/src/overtype.js +++ b/src/overtype.js @@ -7,7 +7,7 @@ import { MarkdownParser } from './parser.js'; import { ShortcutsManager } from './shortcuts.js'; import { generateStyles } from './styles.js'; -import { getTheme, mergeTheme, solar, themeToCSSVars } from './themes.js'; +import { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js'; import { Toolbar } from './toolbar.js'; import { LinkTooltip } from './link-tooltip.js'; import { defaultToolbarButtons } from './toolbar-buttons.js'; @@ -80,6 +80,8 @@ class OverType { static stylesInjected = false; static globalListenersInitialized = false; static instanceCount = 0; + static autoThemeMediaQuery = null; // Media query for auto theme switching + static autoThemeListener = null; // Listener function for auto theme changes /** * Constructor - Always returns an array of instances @@ -137,6 +139,10 @@ class OverType { // Store the original theme option before merging this.instanceTheme = options.theme || null; + // Auto theme tracking for instance-level theme + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; + this.options = this._mergeOptions(options); this.instanceId = ++OverType.instanceCount; this.initialized = false; @@ -156,6 +162,11 @@ class OverType { this._buildFromScratch(); } + // Set up instance theme if provided (including auto theme listener) + if (this.instanceTheme) { + this.setTheme(this.instanceTheme); + } + // Setup shortcuts manager this.shortcuts = new ShortcutsManager(this); @@ -1022,19 +1033,54 @@ class OverType { * @returns {this} Returns this for chaining */ setTheme(theme) { + // Clean up existing auto theme listener if any + this._cleanupAutoThemeListener(); + // Update instance theme this.instanceTheme = theme; - // Get theme object - const themeObj = typeof theme === 'string' ? getTheme(theme) : theme; - const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; + // Handle auto theme + if (theme === 'auto') { + this._setupAutoThemeListener(); + // Apply the initial resolved theme + const resolvedTheme = resolveAutoTheme('auto'); + this._applyResolvedTheme(resolvedTheme); + } else { + // Get theme object for non-auto themes + const themeObj = typeof theme === 'string' ? getTheme(theme) : theme; + const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; - // Update container theme attribute - if (themeName) { - this.container.setAttribute('data-theme', themeName); + // Update container theme attribute + if (themeName) { + this.container.setAttribute('data-theme', themeName); + } + + // Apply CSS variables to container for instance override + if (themeObj && themeObj.colors) { + const cssVars = themeToCSSVars(themeObj.colors); + this.container.style.cssText += cssVars; + } + + // Update preview to reflect new theme + this.updatePreview(); } - // Apply CSS variables to container for instance override + return this; + } + + /** + * Apply a resolved theme name (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + */ + _applyResolvedTheme(themeName) { + const themeObj = getTheme(themeName); + + // Update container with resolved theme, but keep auto in data-theme for tracking + this.container.setAttribute('data-theme', 'auto'); + this.container.setAttribute('data-resolved-theme', themeName); + + // Apply CSS variables if (themeObj && themeObj.colors) { const cssVars = themeToCSSVars(themeObj.colors); this.container.style.cssText += cssVars; @@ -1042,8 +1088,45 @@ class OverType { // Update preview to reflect new theme this.updatePreview(); + } - return this; + /** + * Setup auto theme listener for instance + * @private + */ + _setupAutoThemeListener() { + if (!window.matchMedia) return; + + this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + this.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? 'cave' : 'solar'; + this._applyResolvedTheme(resolvedTheme); + }; + + // Use addEventListener if available (modern browsers) + if (this.autoThemeMediaQuery.addEventListener) { + this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener); + } else if (this.autoThemeMediaQuery.addListener) { + // Fallback for older browsers + this.autoThemeMediaQuery.addListener(this.autoThemeListener); + } + } + + /** + * Clean up auto theme listener for instance + * @private + */ + _cleanupAutoThemeListener() { + if (this.autoThemeMediaQuery && this.autoThemeListener) { + if (this.autoThemeMediaQuery.removeEventListener) { + this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener); + } else if (this.autoThemeMediaQuery.removeListener) { + // Fallback for older browsers + this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + } + this.autoThemeMediaQuery = null; + this.autoThemeListener = null; + } } /** @@ -1251,6 +1334,9 @@ class OverType { * Destroy the editor instance */ destroy() { + // Clean up auto theme listener + this._cleanupAutoThemeListener(); + // Remove instance reference this.element.overTypeInstance = null; OverType.instances.delete(this.element); @@ -1375,8 +1461,78 @@ class OverType { * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - // Process theme - let themeObj = typeof theme === 'string' ? getTheme(theme) : theme; + // Clean up existing auto theme listener + OverType._cleanupGlobalAutoThemeListener(); + + // Handle auto theme at global level + if (theme === 'auto') { + OverType._setupGlobalAutoThemeListener(); + // Apply the initial resolved theme + const resolvedTheme = resolveAutoTheme('auto'); + OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + } else { + // Process theme + let themeObj = typeof theme === 'string' ? getTheme(theme) : theme; + + // Apply custom colors if provided + if (customColors) { + themeObj = mergeTheme(themeObj, customColors); + } + + // Store as current theme + OverType.currentTheme = themeObj; + + // Re-inject styles with new theme + OverType.injectStyles(true); + + // Update all existing instances - update container theme attribute + document.querySelectorAll('.overtype-container').forEach(container => { + const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; + if (themeName) { + container.setAttribute('data-theme', themeName); + } + }); + + // Also handle any old-style wrappers without containers + document.querySelectorAll('.overtype-wrapper').forEach(wrapper => { + if (!wrapper.closest('.overtype-container')) { + const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; + if (themeName) { + wrapper.setAttribute('data-theme', themeName); + } + } + + // Trigger preview update for the instance + const instance = wrapper._instance; + if (instance) { + instance.updatePreview(); + } + }); + + // Update web components (shadow DOM instances) + const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; + document.querySelectorAll('overtype-editor').forEach(webComponent => { + // Set the theme attribute to update the theme name + if (themeName && typeof webComponent.setAttribute === 'function') { + webComponent.setAttribute('theme', themeName); + } + // Also call refreshTheme() to handle cases where the theme name stays the same + // but the theme object's properties have changed + if (typeof webComponent.refreshTheme === 'function') { + webComponent.refreshTheme(); + } + }); + } + } + + /** + * Apply a resolved theme globally (used by auto theme) + * @private + * @param {string} themeName - Resolved theme name + * @param {Object} customColors - Optional color overrides + */ + static _applyGlobalResolvedTheme(themeName, customColors = null) { + let themeObj = getTheme(themeName); // Apply custom colors if provided if (customColors) { @@ -1389,21 +1545,17 @@ class OverType { // Re-inject styles with new theme OverType.injectStyles(true); - // Update all existing instances - update container theme attribute + // Update all containers with resolved theme, but keep 'auto' for tracking document.querySelectorAll('.overtype-container').forEach(container => { - const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; - if (themeName) { - container.setAttribute('data-theme', themeName); - } + container.setAttribute('data-theme', 'auto'); + container.setAttribute('data-resolved-theme', themeName); }); // Also handle any old-style wrappers without containers document.querySelectorAll('.overtype-wrapper').forEach(wrapper => { if (!wrapper.closest('.overtype-container')) { - const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; - if (themeName) { - wrapper.setAttribute('data-theme', themeName); - } + wrapper.setAttribute('data-theme', 'auto'); + wrapper.setAttribute('data-resolved-theme', themeName); } // Trigger preview update for the instance @@ -1413,21 +1565,57 @@ class OverType { } }); - // Update web components (shadow DOM instances) - const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; + // Update web components document.querySelectorAll('overtype-editor').forEach(webComponent => { - // Set the theme attribute to update the theme name - if (themeName && typeof webComponent.setAttribute === 'function') { - webComponent.setAttribute('theme', themeName); + if (typeof webComponent.setAttribute === 'function') { + webComponent.setAttribute('theme', 'auto'); + webComponent.setAttribute('data-resolved-theme', themeName); } - // Also call refreshTheme() to handle cases where the theme name stays the same - // but the theme object's properties have changed if (typeof webComponent.refreshTheme === 'function') { webComponent.refreshTheme(); } }); } + /** + * Setup global auto theme listener + * @private + */ + static _setupGlobalAutoThemeListener() { + if (!window.matchMedia) return; + + OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + OverType.autoThemeListener = (event) => { + const resolvedTheme = event.matches ? 'cave' : 'solar'; + OverType._applyGlobalResolvedTheme(resolvedTheme); + }; + + // Use addEventListener if available (modern browsers) + if (OverType.autoThemeMediaQuery.addEventListener) { + OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener); + } else if (OverType.autoThemeMediaQuery.addListener) { + // Fallback for older browsers + OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener); + } + } + + /** + * Clean up global auto theme listener + * @private + */ + static _cleanupGlobalAutoThemeListener() { + if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) { + if (OverType.autoThemeMediaQuery.removeEventListener) { + OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener); + } else if (OverType.autoThemeMediaQuery.removeListener) { + // Fallback for older browsers + OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener); + } + OverType.autoThemeMediaQuery = null; + OverType.autoThemeListener = null; + } + } + /** * Set global code highlighter for all OverType instances * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML diff --git a/src/themes.js b/src/themes.js index 6566ec9..9af90c8 100644 --- a/src/themes.js +++ b/src/themes.js @@ -81,12 +81,23 @@ export const cave = { } }; +/** + * Auto theme - Automatically switches between solar and cave based on system preference + * This is a special marker theme that triggers automatic theme switching + */ +export const auto = { + name: 'auto', + // The auto theme doesn't have its own colors; it uses solar or cave dynamically + colors: solar.colors // Default to solar colors for initial render +}; + /** * Default themes registry */ export const themes = { solar, cave, + auto, // Aliases for backward compatibility light: solar, dark: cave @@ -106,6 +117,30 @@ export function getTheme(theme) { return theme; } +/** + * Resolve auto theme to actual theme based on system color scheme preference + * @param {string} themeName - Theme name to resolve + * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name) + */ +export function resolveAutoTheme(themeName) { + if (themeName !== 'auto') { + return themeName; + } + + // Check for system dark mode preference + const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; + return isDarkMode ? 'cave' : 'solar'; +} + +/** + * Get the current system color scheme preference + * @returns {string} 'dark' or 'light' + */ +export function getSystemColorScheme() { + const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; + return isDarkMode ? 'dark' : 'light'; +} + /** * Apply theme colors to CSS variables * @param {Object} colors - Theme colors object diff --git a/test/auto-theme.test.js b/test/auto-theme.test.js new file mode 100644 index 0000000..c9fac04 --- /dev/null +++ b/test/auto-theme.test.js @@ -0,0 +1,156 @@ +/** + * Tests for auto theme functionality + */ + +import { expect } from '@playwright/test'; +import { test } from '@playwright/test'; + +test.describe('Auto Theme', () => { + test.beforeEach(async ({ page }) => { + await page.goto('/examples/auto-theme.html'); + }); + + test('should initialize with auto theme', async ({ page }) => { + // Check that the editor has auto theme attribute + const themeAttr = await page.locator('.overtype-container').getAttribute('data-theme'); + expect(themeAttr).toBe('auto'); + }); + + test('should have resolved theme attribute', async ({ page }) => { + // Check that the editor has a resolved theme + const resolvedTheme = await page.locator('.overtype-container').getAttribute('data-resolved-theme'); + expect(['solar', 'cave']).toContain(resolvedTheme); + }); + + test('should respond to system theme preference', async ({ page, context }) => { + // Set system to dark mode + await context.emulateMedia({ colorScheme: 'dark' }); + await page.reload(); + + // Wait for the theme to be applied + await page.waitForTimeout(100); + + const resolvedTheme = await page.locator('.overtype-container').getAttribute('data-resolved-theme'); + expect(resolvedTheme).toBe('cave'); + + // Set system to light mode + await context.emulateMedia({ colorScheme: 'light' }); + await page.reload(); + + // Wait for the theme to be applied + await page.waitForTimeout(100); + + const resolvedThemeLight = await page.locator('.overtype-container').getAttribute('data-resolved-theme'); + expect(resolvedThemeLight).toBe('solar'); + }); + + test('should switch theme when dropdown changed', async ({ page }) => { + const select = page.locator('#theme-select'); + + // Change to cave + await select.selectOption('cave'); + const themeAttr = await page.locator('.overtype-container').getAttribute('data-theme'); + expect(themeAttr).toBe('cave'); + + // Change back to auto + await select.selectOption('auto'); + const autoTheme = await page.locator('.overtype-container').getAttribute('data-theme'); + expect(autoTheme).toBe('auto'); + }); + + test('should show system theme info when button clicked', async ({ page }) => { + // Mock the alert dialog + page.on('dialog', async dialog => { + const message = dialog.message(); + expect(message).toContain('System Theme:'); + expect(message).toContain('Editor Theme:'); + await dialog.accept(); + }); + + // Click the info button + await page.click('#get-info-btn'); + }); +}); + +test.describe('Auto Theme - Instance Level', () => { + test('should work with instance-level theme setting', async ({ page, browser }) => { + // Create a test page + await page.setContent(` + + + + + + +
    + + + + `); + + // Wait for the editor to initialize + await page.waitForTimeout(500); + + // Check theme attribute + const themeAttr = await page.locator('.overtype-container').getAttribute('data-theme'); + expect(themeAttr).toBe('auto'); + + // Test switching to a different theme + await page.evaluate(() => { + window.editor.setTheme('solar'); + }); + + const newTheme = await page.locator('.overtype-container').getAttribute('data-theme'); + expect(newTheme).toBe('solar'); + }); +}); + +test.describe('Auto Theme - Global Level', () => { + test('should work with global theme setting', async ({ page }) => { + await page.setContent(` + + + + + + +
    +
    + + + + `); + + await page.waitForTimeout(500); + + // Check both editors have auto theme + const containers = await page.locator('.overtype-container').all(); + + for (const container of containers) { + const theme = await container.getAttribute('data-theme'); + expect(theme).toBe('auto'); + + const resolved = await container.getAttribute('data-resolved-theme'); + expect(['solar', 'cave']).toContain(resolved); + } + }); +}); diff --git a/website/examples/auto-theme.html b/website/examples/auto-theme.html new file mode 100644 index 0000000..0bd9055 --- /dev/null +++ b/website/examples/auto-theme.html @@ -0,0 +1,243 @@ + + + + + + OverType - Auto Theme Example + + + +

    Auto Theme Example

    + +
    + The auto theme automatically switches between solar (light) and cave (dark) themes + based on your system's color scheme preference. Try changing your system theme to see it update in real-time! +
    + +
    + How to test: Change your system's appearance settings between light and dark mode. + The editor will automatically switch themes to match your preference. +
    + +
    +
    + + +
    + +
    + +
    +
    + +
    + + + + + diff --git a/website/examples/index.html b/website/examples/index.html index c41d5e6..28250bf 100644 --- a/website/examples/index.html +++ b/website/examples/index.html @@ -122,6 +122,16 @@

    Custom Theme

    Create your own color theme or customize existing themes.

    Theming + +

    Auto Theme

    +

    Automatically switch between light and dark themes based on system preference.

    + Theming +
    + +

    Auto Theme

    +

    Automatically switch between light and dark themes based on system preference.

    + Theming +

    Dynamic Editing

    diff --git a/website/index.html b/website/index.html index 495689c..281a19c 100644 --- a/website/index.html +++ b/website/index.html @@ -612,14 +612,14 @@

    START BUILDING

    // Initialize all main editors new OT('.demo-editor', { value: samples.main, - theme: 'cave' + theme: 'auto' }); // Initialize all toolbar editors new OT('.demo-editor-toolbar', { value: samples.toolbar, toolbar: true, - theme: 'cave' + theme: 'auto' }); }); From cf2fc9f9ab0cea48d77719afaaf24c322982231a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:22:14 +0000 Subject: [PATCH 2/8] Initial plan From a3a833c874f8d078ec67df340824e6a3ff1498bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:23:43 +0000 Subject: [PATCH 3/8] Initial exploration complete - ready to optimize auto theme bundle size Co-authored-by: dido739 <152557154+dido739@users.noreply.github.com> --- dist/overtype.esm.js.map | 2 +- dist/overtype.js.map | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/overtype.esm.js.map b/dist/overtype.esm.js.map index a591ee9..b669962 100644 --- a/dist/overtype.esm.js.map +++ b/dist/overtype.esm.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js", "../src/overtype.js"], - "sourcesContent": ["/**\r\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\r\n *\r\n * Key principles:\r\n * - Every character must occupy the exact same position as in the textarea\r\n * - No font-size changes, no padding/margin on inline elements\r\n * - Markdown tokens remain visible but styled\r\n */\r\nexport class MarkdownParser {\r\n // Track link index for anchor naming\r\n static linkIndex = 0;\r\n\r\n // Global code highlighter function\r\n static codeHighlighter = null;\r\n\r\n // Custom syntax processor function\r\n static customSyntax = null;\r\n\r\n /**\r\n * Reset link index (call before parsing a new document)\r\n */\r\n static resetLinkIndex() {\r\n this.linkIndex = 0;\r\n }\r\n\r\n /**\r\n * Set global code highlighter function\r\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n */\r\n static setCodeHighlighter(highlighter) {\r\n this.codeHighlighter = highlighter;\r\n }\r\n\r\n /**\r\n * Set custom syntax processor function\r\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\r\n */\r\n static setCustomSyntax(processor) {\r\n this.customSyntax = processor;\r\n }\r\n\r\n /**\r\n * Apply custom syntax processor to parsed HTML\r\n * @param {string} html - Parsed HTML line\r\n * @returns {string} HTML with custom syntax applied\r\n */\r\n static applyCustomSyntax(html) {\r\n if (this.customSyntax) {\r\n return this.customSyntax(html);\r\n }\r\n return html;\r\n }\r\n\r\n /**\r\n * Escape HTML special characters\r\n * @param {string} text - Raw text to escape\r\n * @returns {string} Escaped HTML-safe text\r\n */\r\n static escapeHtml(text) {\r\n const map = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": '''\r\n };\r\n return text.replace(/[&<>\"']/g, m => map[m]);\r\n }\r\n\r\n /**\r\n * Preserve leading spaces as non-breaking spaces\r\n * @param {string} html - HTML string\r\n * @param {string} originalLine - Original line with spaces\r\n * @returns {string} HTML with preserved indentation\r\n */\r\n static preserveIndentation(html, originalLine) {\r\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\r\n const indentation = leadingSpaces.replace(/ /g, ' ');\r\n return html.replace(/^\\s*/, indentation);\r\n }\r\n\r\n /**\r\n * Parse headers (h1-h3 only)\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed HTML with header styling\r\n */\r\n static parseHeader(html) {\r\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\r\n const level = hashes.length;\r\n return `${hashes} ${content}`;\r\n });\r\n }\r\n\r\n /**\r\n * Parse horizontal rules\r\n * @param {string} html - HTML line to parse\r\n * @returns {string|null} Parsed horizontal rule or null\r\n */\r\n static parseHorizontalRule(html) {\r\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\r\n return `
    ${html}
    `;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse blockquotes\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed blockquote\r\n */\r\n static parseBlockquote(html) {\r\n return html.replace(/^> (.+)$/, (match, content) => {\r\n return `> ${content}`;\r\n });\r\n }\r\n\r\n /**\r\n * Parse bullet lists\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed bullet list item\r\n */\r\n static parseBulletList(html) {\r\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\r\n return `${indent}
  • ${marker} ${content}
  • `;\r\n });\r\n }\r\n\r\n /**\r\n * Parse task lists (GitHub Flavored Markdown checkboxes)\r\n * @param {string} html - HTML line to parse\r\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\r\n * @returns {string} Parsed task list item\r\n */\r\n static parseTaskList(html, isPreviewMode = false) {\r\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\r\n if (isPreviewMode) {\r\n // Preview mode: render actual checkbox\r\n const isChecked = checked.toLowerCase() === 'x';\r\n return `${indent}
  • ${content}
  • `;\r\n } else {\r\n // Normal mode: keep syntax visible for alignment\r\n return `${indent}
  • - [${checked}] ${content}
  • `;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Parse numbered lists\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed numbered list item\r\n */\r\n static parseNumberedList(html) {\r\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\r\n return `${indent}
  • ${marker} ${content}
  • `;\r\n });\r\n }\r\n\r\n /**\r\n * Parse code blocks (markers only)\r\n * @param {string} html - HTML line to parse\r\n * @returns {string|null} Parsed code fence or null\r\n */\r\n static parseCodeBlock(html) {\r\n // The line must start with three backticks and have no backticks after subsequent text\r\n const codeFenceRegex = /^`{3}[^`]*$/;\r\n if (codeFenceRegex.test(html)) {\r\n return `
    ${html}
    `;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse bold text\r\n * @param {string} html - HTML with potential bold markdown\r\n * @returns {string} HTML with bold styling\r\n */\r\n static parseBold(html) {\r\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\r\n html = html.replace(/__(.+?)__/g, '__$1__');\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse italic text\r\n * Note: Uses lookbehind assertions - requires modern browsers\r\n * @param {string} html - HTML with potential italic markdown\r\n * @returns {string} HTML with italic styling\r\n */\r\n static parseItalic(html) {\r\n // Single asterisk - must not be adjacent to other asterisks\r\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\r\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\r\n\r\n // Single underscore - must be at word boundaries to avoid matching inside words\r\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\r\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\r\n\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse strikethrough text\r\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\r\n * @param {string} html - HTML with potential strikethrough markdown\r\n * @returns {string} HTML with strikethrough styling\r\n */\r\n static parseStrikethrough(html) {\r\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\r\n html = html.replace(/(?~~$1~~');\r\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\r\n html = html.replace(/(?~$1~');\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse inline code\r\n * @param {string} html - HTML with potential code markdown\r\n * @returns {string} HTML with code styling\r\n */\r\n static parseInlineCode(html) {\r\n // Must have equal number of backticks before and after inline code\r\n //\r\n // Regex explainer:\r\n // (?$1$2$3');\r\n }\r\n\r\n /**\r\n * Sanitize URL to prevent XSS attacks\r\n * @param {string} url - URL to sanitize\r\n * @returns {string} Safe URL or '#' if dangerous\r\n */\r\n static sanitizeUrl(url) {\r\n // Trim whitespace and convert to lowercase for protocol check\r\n const trimmed = url.trim();\r\n const lower = trimmed.toLowerCase();\r\n\r\n // Allow safe protocols\r\n const safeProtocols = [\r\n 'http://',\r\n 'https://',\r\n 'mailto:',\r\n 'ftp://',\r\n 'ftps://'\r\n ];\r\n\r\n // Check if URL starts with a safe protocol\r\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\r\n\r\n // Allow relative URLs (starting with / or # or no protocol)\r\n const isRelative = trimmed.startsWith('/') ||\r\n trimmed.startsWith('#') ||\r\n trimmed.startsWith('?') ||\r\n trimmed.startsWith('.') ||\r\n (!trimmed.includes(':') && !trimmed.includes('//'));\r\n\r\n // If safe protocol or relative URL, return as-is\r\n if (hasSafeProtocol || isRelative) {\r\n return url;\r\n }\r\n\r\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\r\n return '#';\r\n }\r\n\r\n /**\r\n * Parse links\r\n * @param {string} html - HTML with potential link markdown\r\n * @returns {string} HTML with link styling\r\n */\r\n static parseLinks(html) {\r\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\r\n const anchorName = `--link-${this.linkIndex++}`;\r\n // Sanitize URL to prevent XSS attacks\r\n const safeUrl = this.sanitizeUrl(url);\r\n // Use real href - pointer-events handles click prevention in normal mode\r\n return `
    [${text}](${url})`;\r\n });\r\n }\r\n\r\n /**\r\n * Identify and protect sanctuaries (code and links) before parsing\r\n * @param {string} text - Text with potential markdown\r\n * @returns {Object} Object with protected text and sanctuary map\r\n */\r\n static identifyAndProtectSanctuaries(text) {\r\n const sanctuaries = new Map();\r\n let sanctuaryCounter = 0;\r\n let protectedText = text;\r\n \r\n // Create a map to track protected regions (URLs should not be processed)\r\n const protectedRegions = [];\r\n \r\n // First, find all links and mark their URL regions as protected\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n let linkMatch;\r\n while ((linkMatch = linkRegex.exec(text)) !== null) {\r\n // Calculate the exact position of the URL part\r\n // linkMatch.index is the start of the match\r\n // We need to find where \"](\" starts, then add 2 to get URL start\r\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\r\n const urlStart = bracketPos + 2;\r\n const urlEnd = urlStart + linkMatch[2].length;\r\n protectedRegions.push({ start: urlStart, end: urlEnd });\r\n }\r\n \r\n // Now protect inline code, but skip if it's inside a protected region (URL)\r\n const codeRegex = /(? \r\n codeStart >= region.start && codeEnd <= region.end\r\n );\r\n \r\n if (!inProtectedRegion) {\r\n codeMatches.push({\r\n match: codeMatch[0],\r\n index: codeMatch.index,\r\n openTicks: codeMatch[1],\r\n content: codeMatch[2],\r\n closeTicks: codeMatch[3]\r\n });\r\n }\r\n }\r\n \r\n // Replace code matches from end to start to preserve indices\r\n codeMatches.sort((a, b) => b.index - a.index);\r\n codeMatches.forEach(codeInfo => {\r\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\r\n sanctuaries.set(placeholder, {\r\n type: 'code',\r\n original: codeInfo.match,\r\n openTicks: codeInfo.openTicks,\r\n content: codeInfo.content,\r\n closeTicks: codeInfo.closeTicks\r\n });\r\n protectedText = protectedText.substring(0, codeInfo.index) + \r\n placeholder + \r\n protectedText.substring(codeInfo.index + codeInfo.match.length);\r\n });\r\n \r\n // Then protect links - they can contain sanctuary placeholders for code but not raw code\r\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\r\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\r\n sanctuaries.set(placeholder, {\r\n type: 'link',\r\n original: match,\r\n linkText,\r\n url\r\n });\r\n return placeholder;\r\n });\r\n \r\n return { protectedText, sanctuaries };\r\n }\r\n \r\n /**\r\n * Restore and transform sanctuaries back to HTML\r\n * @param {string} html - HTML with sanctuary placeholders\r\n * @param {Map} sanctuaries - Map of sanctuaries to restore\r\n * @returns {string} HTML with sanctuaries restored and transformed\r\n */\r\n static restoreAndTransformSanctuaries(html, sanctuaries) {\r\n // Sort sanctuary placeholders by position to restore in order\r\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\r\n const indexA = html.indexOf(a);\r\n const indexB = html.indexOf(b);\r\n return indexA - indexB;\r\n });\r\n \r\n placeholders.forEach(placeholder => {\r\n const sanctuary = sanctuaries.get(placeholder);\r\n let replacement;\r\n \r\n if (sanctuary.type === 'code') {\r\n // Transform code sanctuary to HTML\r\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\r\n } else if (sanctuary.type === 'link') {\r\n // For links, we need to process the link text for markdown\r\n let processedLinkText = sanctuary.linkText;\r\n \r\n // First restore any sanctuary placeholders that were already in the link text\r\n // (e.g., inline code that was protected before the link)\r\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\r\n if (processedLinkText.includes(innerPlaceholder)) {\r\n if (innerSanctuary.type === 'code') {\r\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\r\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\r\n }\r\n }\r\n });\r\n \r\n // Now parse other markdown in the link text (bold, italic, etc)\r\n processedLinkText = this.parseStrikethrough(processedLinkText);\r\n processedLinkText = this.parseBold(processedLinkText);\r\n processedLinkText = this.parseItalic(processedLinkText);\r\n \r\n // Transform link sanctuary to HTML\r\n // URL should NOT be processed for markdown - use it as-is\r\n const anchorName = `--link-${this.linkIndex++}`;\r\n const safeUrl = this.sanitizeUrl(sanctuary.url);\r\n replacement = `[${processedLinkText}](${sanctuary.url})`;\r\n }\r\n \r\n html = html.replace(placeholder, replacement);\r\n });\r\n \r\n return html;\r\n }\r\n \r\n /**\r\n * Parse all inline elements in correct order\r\n * @param {string} text - Text with potential inline markdown\r\n * @returns {string} HTML with all inline styling\r\n */\r\n static parseInlineElements(text) {\r\n // Step 1: Identify and protect sanctuaries (code and links)\r\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\r\n \r\n // Step 2: Parse other inline elements on protected text\r\n let html = protectedText;\r\n html = this.parseStrikethrough(html);\r\n html = this.parseBold(html);\r\n html = this.parseItalic(html);\r\n \r\n // Step 3: Restore and transform sanctuaries\r\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\r\n \r\n return html;\r\n }\r\n\r\n /**\r\n * Parse a single line of markdown\r\n * @param {string} line - Raw markdown line\r\n * @returns {string} Parsed HTML line\r\n */\r\n static parseLine(line, isPreviewMode = false) {\r\n let html = this.escapeHtml(line);\r\n\r\n // Preserve indentation\r\n html = this.preserveIndentation(html, line);\r\n\r\n // Check for block elements first\r\n const horizontalRule = this.parseHorizontalRule(html);\r\n if (horizontalRule) return horizontalRule;\r\n\r\n const codeBlock = this.parseCodeBlock(html);\r\n if (codeBlock) return codeBlock;\r\n\r\n // Parse block elements\r\n html = this.parseHeader(html);\r\n html = this.parseBlockquote(html);\r\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\r\n html = this.parseBulletList(html);\r\n html = this.parseNumberedList(html);\r\n\r\n // Parse inline elements\r\n html = this.parseInlineElements(html);\r\n\r\n // Wrap in div to maintain line structure\r\n if (html.trim() === '') {\r\n // Intentionally use   for empty lines to maintain vertical spacing\r\n // This causes a 0->1 character count difference but preserves visual alignment\r\n return '
     
    ';\r\n }\r\n\r\n return `
    ${html}
    `;\r\n }\r\n\r\n /**\r\n * Parse full markdown text\r\n * @param {string} text - Full markdown text\r\n * @param {number} activeLine - Currently active line index (optional)\r\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Parsed HTML\r\n */\r\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\r\n // Reset link counter for each parse\r\n this.resetLinkIndex();\r\n\r\n const lines = text.split('\\n');\r\n let inCodeBlock = false;\r\n\r\n const parsedLines = lines.map((line, index) => {\r\n // Show raw markdown on active line if requested\r\n if (showActiveLineRaw && index === activeLine) {\r\n const content = this.escapeHtml(line) || ' ';\r\n return `
    ${content}
    `;\r\n }\r\n\r\n // Check if this line is a code fence\r\n const codeFenceRegex = /^```[^`]*$/;\r\n if (codeFenceRegex.test(line)) {\r\n inCodeBlock = !inCodeBlock;\r\n // Parse fence markers normally to get styled output\r\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\r\n }\r\n\r\n // If we're inside a code block, don't parse as markdown\r\n if (inCodeBlock) {\r\n const escaped = this.escapeHtml(line);\r\n const indented = this.preserveIndentation(escaped, line);\r\n return `
    ${indented || ' '}
    `;\r\n }\r\n\r\n // Otherwise, parse the markdown normally\r\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\r\n });\r\n\r\n // Join without newlines to prevent extra spacing\r\n const html = parsedLines.join('');\r\n\r\n // Apply post-processing for list consolidation\r\n return this.postProcessHTML(html, instanceHighlighter);\r\n }\r\n\r\n /**\r\n * Post-process HTML to consolidate lists and code blocks\r\n * @param {string} html - HTML to post-process\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\r\n */\r\n static postProcessHTML(html, instanceHighlighter) {\r\n // Check if we're in a browser environment\r\n if (typeof document === 'undefined' || !document) {\r\n // In Node.js environment - do manual post-processing\r\n return this.postProcessHTMLManual(html, instanceHighlighter);\r\n }\r\n\r\n // Parse HTML string into DOM\r\n const container = document.createElement('div');\r\n container.innerHTML = html;\r\n\r\n let currentList = null;\r\n let listType = null;\r\n let currentCodeBlock = null;\r\n let inCodeBlock = false;\r\n\r\n // Process all direct children - need to be careful with live NodeList\r\n const children = Array.from(container.children);\r\n\r\n for (let i = 0; i < children.length; i++) {\r\n const child = children[i];\r\n\r\n // Skip if child was already processed/removed\r\n if (!child.parentNode) continue;\r\n\r\n // Check for code fence start/end\r\n const codeFence = child.querySelector('.code-fence');\r\n if (codeFence) {\r\n const fenceText = codeFence.textContent;\r\n if (fenceText.startsWith('```')) {\r\n if (!inCodeBlock) {\r\n // Start of code block - keep fence visible, then add pre/code\r\n inCodeBlock = true;\r\n\r\n // Create the code block that will follow the fence\r\n currentCodeBlock = document.createElement('pre');\r\n const codeElement = document.createElement('code');\r\n currentCodeBlock.appendChild(codeElement);\r\n currentCodeBlock.className = 'code-block';\r\n\r\n // Extract language if present\r\n const lang = fenceText.slice(3).trim();\r\n if (lang) {\r\n codeElement.className = `language-${lang}`;\r\n }\r\n\r\n // Insert code block after the fence div (don't remove the fence)\r\n container.insertBefore(currentCodeBlock, child.nextSibling);\r\n\r\n // Store reference to the code element for adding content\r\n currentCodeBlock._codeElement = codeElement;\r\n currentCodeBlock._language = lang;\r\n currentCodeBlock._codeContent = '';\r\n continue;\r\n } else {\r\n // End of code block - apply highlighting if needed\r\n // Use instance highlighter if provided, otherwise fall back to global highlighter\r\n const highlighter = instanceHighlighter || this.codeHighlighter;\r\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\r\n try {\r\n const result = highlighter(\r\n currentCodeBlock._codeContent,\r\n currentCodeBlock._language || ''\r\n );\r\n\r\n // Check if result is a Promise (async highlighter)\r\n if (result && typeof result.then === 'function') {\r\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\r\n // Keep the plain text fallback that was already set\r\n } else {\r\n // Synchronous highlighter\r\n // Verify highlighter returned non-empty string\r\n if (result && typeof result === 'string' && result.trim()) {\r\n currentCodeBlock._codeElement.innerHTML = result;\r\n }\r\n // else: keep the plain text fallback that was already set\r\n }\r\n } catch (error) {\r\n console.warn('Code highlighting failed:', error);\r\n // Keep the plain text content as fallback\r\n }\r\n }\r\n\r\n inCodeBlock = false;\r\n currentCodeBlock = null;\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n // Check if we're in a code block - any div that's not a code fence\r\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\r\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\r\n // Add the line content to the code block content (for highlighting)\r\n if (currentCodeBlock._codeContent.length > 0) {\r\n currentCodeBlock._codeContent += '\\n';\r\n }\r\n // Get the actual text content, preserving spaces\r\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\r\n currentCodeBlock._codeContent += lineText;\r\n\r\n // Also add to the code element (fallback if no highlighter)\r\n if (codeElement.textContent.length > 0) {\r\n codeElement.textContent += '\\n';\r\n }\r\n codeElement.textContent += lineText;\r\n child.remove();\r\n continue;\r\n }\r\n\r\n // Check if this div contains a list item\r\n let listItem = null;\r\n if (child.tagName === 'DIV') {\r\n // Look for li inside the div\r\n listItem = child.querySelector('li');\r\n }\r\n\r\n if (listItem) {\r\n const isBullet = listItem.classList.contains('bullet-list');\r\n const isOrdered = listItem.classList.contains('ordered-list');\r\n\r\n if (!isBullet && !isOrdered) {\r\n currentList = null;\r\n listType = null;\r\n continue;\r\n }\r\n\r\n const newType = isBullet ? 'ul' : 'ol';\r\n\r\n // Start new list or continue current\r\n if (!currentList || listType !== newType) {\r\n currentList = document.createElement(newType);\r\n container.insertBefore(currentList, child);\r\n listType = newType;\r\n }\r\n\r\n // Extract and preserve indentation from the div before moving the list item\r\n const indentationNodes = [];\r\n for (const node of child.childNodes) {\r\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\r\n // This is a text node containing only non-breaking spaces (indentation)\r\n indentationNodes.push(node.cloneNode(true));\r\n } else if (node === listItem) {\r\n break; // Stop when we reach the list item\r\n }\r\n }\r\n\r\n // Add indentation to the list item\r\n indentationNodes.forEach(node => {\r\n listItem.insertBefore(node, listItem.firstChild);\r\n });\r\n\r\n // Move the list item to the current list\r\n currentList.appendChild(listItem);\r\n\r\n // Remove the now-empty div wrapper\r\n child.remove();\r\n } else {\r\n // Non-list element ends current list\r\n currentList = null;\r\n listType = null;\r\n }\r\n }\r\n\r\n return container.innerHTML;\r\n }\r\n\r\n /**\r\n * Manual post-processing for Node.js environments (without DOM)\r\n * @param {string} html - HTML to post-process\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Post-processed HTML\r\n */\r\n static postProcessHTMLManual(html, instanceHighlighter) {\r\n let processed = html;\r\n\r\n // Process unordered lists\r\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\r\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\r\n if (divs.length > 0) {\r\n const items = divs.map(div => {\r\n // Extract indentation and list item\r\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\r\n\r\n if (indentMatch && listItemMatch) {\r\n const indentation = indentMatch[1];\r\n const listItem = listItemMatch[0];\r\n // Insert indentation at the start of the list item content\r\n return listItem.replace(/
  • /, `
  • ${indentation}`);\r\n }\r\n return listItemMatch ? listItemMatch[0] : '';\r\n }).filter(Boolean);\r\n\r\n return '
      ' + items.join('') + '
    ';\r\n }\r\n return match;\r\n });\r\n\r\n // Process ordered lists\r\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\r\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\r\n if (divs.length > 0) {\r\n const items = divs.map(div => {\r\n // Extract indentation and list item\r\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\r\n\r\n if (indentMatch && listItemMatch) {\r\n const indentation = indentMatch[1];\r\n const listItem = listItemMatch[0];\r\n // Insert indentation at the start of the list item content\r\n return listItem.replace(/
  • /, `
  • ${indentation}`);\r\n }\r\n return listItemMatch ? listItemMatch[0] : '';\r\n }).filter(Boolean);\r\n\r\n return '
      ' + items.join('') + '
    ';\r\n }\r\n return match;\r\n });\r\n\r\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\r\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\r\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\r\n // Extract the content between fences\r\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\r\n const codeContent = lines.map(line => {\r\n // Extract text from each div - content is already escaped\r\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\r\n .replace(/ /g, ' ');\r\n return text;\r\n }).join('\\n');\r\n\r\n // Extract language from the opening fence\r\n const lang = openFence.slice(3).trim();\r\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\r\n\r\n // Apply code highlighting if available\r\n let highlightedContent = codeContent;\r\n // Use instance highlighter if provided, otherwise fall back to global highlighter\r\n const highlighter = instanceHighlighter || this.codeHighlighter;\r\n if (highlighter) {\r\n try {\r\n // CRITICAL: Decode HTML entities before passing to highlighter\r\n // In the DOM path, textContent automatically decodes entities.\r\n // In the manual path, we need to decode explicitly to avoid double-escaping.\r\n const decodedCode = codeContent\r\n .replace(/"/g, '\"')\r\n .replace(/'/g, \"'\")\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\r\n\r\n const result = highlighter(decodedCode, lang);\r\n\r\n // Check if result is a Promise (async highlighter)\r\n // Note: In Node.js context, we can't easily defer rendering, so we warn\r\n if (result && typeof result.then === 'function') {\r\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\r\n // Fall back to escaped content\r\n } else {\r\n // Synchronous highlighter - verify returned non-empty string\r\n if (result && typeof result === 'string' && result.trim()) {\r\n highlightedContent = result;\r\n }\r\n // else: keep the escaped codeContent as fallback\r\n }\r\n } catch (error) {\r\n console.warn('Code highlighting failed:', error);\r\n // Fall back to original content\r\n }\r\n }\r\n\r\n // Keep fence markers visible as separate divs, with pre/code block between them\r\n let result = `
    ${openFence}
    `;\r\n // Use highlighted content if available, otherwise use escaped content\r\n result += `
    ${highlightedContent}
    `;\r\n result += `
    ${closeFence}
    `;\r\n\r\n return result;\r\n });\r\n\r\n return processed;\r\n }\r\n\r\n /**\r\n * List pattern definitions\r\n */\r\n static LIST_PATTERNS = {\r\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\r\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\r\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\r\n };\r\n\r\n /**\r\n * Get list context at cursor position\r\n * @param {string} text - Full text content\r\n * @param {number} cursorPosition - Current cursor position\r\n * @returns {Object} List context information\r\n */\r\n static getListContext(text, cursorPosition) {\r\n // Find the line containing the cursor\r\n const lines = text.split('\\n');\r\n let currentPos = 0;\r\n let lineIndex = 0;\r\n let lineStart = 0;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const lineLength = lines[i].length;\r\n if (currentPos + lineLength >= cursorPosition) {\r\n lineIndex = i;\r\n lineStart = currentPos;\r\n break;\r\n }\r\n currentPos += lineLength + 1; // +1 for newline\r\n }\r\n\r\n const currentLine = lines[lineIndex];\r\n const lineEnd = lineStart + currentLine.length;\r\n\r\n // Check for checkbox first (most specific)\r\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\r\n if (checkboxMatch) {\r\n return {\r\n inList: true,\r\n listType: 'checkbox',\r\n indent: checkboxMatch[1],\r\n marker: '-',\r\n checked: checkboxMatch[2] === 'x',\r\n content: checkboxMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\r\n };\r\n }\r\n\r\n // Check for bullet list\r\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\r\n if (bulletMatch) {\r\n return {\r\n inList: true,\r\n listType: 'bullet',\r\n indent: bulletMatch[1],\r\n marker: bulletMatch[2],\r\n content: bulletMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\r\n };\r\n }\r\n\r\n // Check for numbered list\r\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\r\n if (numberedMatch) {\r\n return {\r\n inList: true,\r\n listType: 'numbered',\r\n indent: numberedMatch[1],\r\n marker: parseInt(numberedMatch[2]),\r\n content: numberedMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\r\n };\r\n }\r\n\r\n // Not in a list\r\n return {\r\n inList: false,\r\n listType: null,\r\n indent: '',\r\n marker: null,\r\n content: currentLine,\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart\r\n };\r\n }\r\n\r\n /**\r\n * Create a new list item based on context\r\n * @param {Object} context - List context from getListContext\r\n * @returns {string} New list item text\r\n */\r\n static createNewListItem(context) {\r\n switch (context.listType) {\r\n case 'bullet':\r\n return `${context.indent}${context.marker} `;\r\n case 'numbered':\r\n return `${context.indent}${context.marker + 1}. `;\r\n case 'checkbox':\r\n return `${context.indent}- [ ] `;\r\n default:\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Renumber all numbered lists in text\r\n * @param {string} text - Text containing numbered lists\r\n * @returns {string} Text with renumbered lists\r\n */\r\n static renumberLists(text) {\r\n const lines = text.split('\\n');\r\n const numbersByIndent = new Map();\r\n let inList = false;\r\n\r\n const result = lines.map(line => {\r\n const match = line.match(this.LIST_PATTERNS.numbered);\r\n\r\n if (match) {\r\n const indent = match[1];\r\n const indentLevel = indent.length;\r\n const content = match[3];\r\n\r\n // If we weren't in a list or indent changed, reset lower levels\r\n if (!inList) {\r\n numbersByIndent.clear();\r\n }\r\n\r\n // Get the next number for this indent level\r\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\r\n numbersByIndent.set(indentLevel, currentNumber);\r\n\r\n // Clear deeper indent levels\r\n for (const [level] of numbersByIndent) {\r\n if (level > indentLevel) {\r\n numbersByIndent.delete(level);\r\n }\r\n }\r\n\r\n inList = true;\r\n return `${indent}${currentNumber}. ${content}`;\r\n } else {\r\n // Not a numbered list item\r\n if (line.trim() === '' || !line.match(/^\\s/)) {\r\n // Empty line or non-indented line breaks the list\r\n inList = false;\r\n numbersByIndent.clear();\r\n }\r\n return line;\r\n }\r\n });\r\n\r\n return result.join('\\n');\r\n }\r\n}\r\n", "/**\r\n * Keyboard shortcuts handler for OverType editor\r\n * Delegates to editor.performAction for consistent behavior\r\n */\r\n\r\n/**\r\n * ShortcutsManager - Handles keyboard shortcuts for the editor\r\n */\r\nexport class ShortcutsManager {\r\n constructor(editor) {\r\n this.editor = editor;\r\n }\r\n\r\n /**\r\n * Handle keydown events - called by OverType\r\n * @param {KeyboardEvent} event - The keyboard event\r\n * @returns {boolean} Whether the event was handled\r\n */\r\n handleKeydown(event) {\r\n const isMac = navigator.platform.toLowerCase().includes('mac');\r\n const modKey = isMac ? event.metaKey : event.ctrlKey;\r\n\r\n if (!modKey) return false;\r\n\r\n let actionId = null;\r\n\r\n switch (event.key.toLowerCase()) {\r\n case 'b':\r\n if (!event.shiftKey) actionId = 'toggleBold';\r\n break;\r\n case 'i':\r\n if (!event.shiftKey) actionId = 'toggleItalic';\r\n break;\r\n case 'k':\r\n if (!event.shiftKey) actionId = 'insertLink';\r\n break;\r\n case '7':\r\n if (event.shiftKey) actionId = 'toggleNumberedList';\r\n break;\r\n case '8':\r\n if (event.shiftKey) actionId = 'toggleBulletList';\r\n break;\r\n }\r\n\r\n if (actionId) {\r\n event.preventDefault();\r\n this.editor.performAction(actionId, event);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy() {\r\n // Nothing to clean up since we don't add our own listener\r\n }\r\n}\r\n", "/**\r\n * Built-in themes for OverType editor\r\n * Each theme provides a complete color palette for the editor\r\n */\r\n\r\n/**\r\n * Solar theme - Light, warm and bright\r\n */\r\nexport const solar = {\r\n name: 'solar',\r\n colors: {\r\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\r\n bgSecondary: '#ffffff', // White - editor background\r\n text: '#0d3b66', // Yale Blue - main text\r\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\r\n textSecondary: '#5a7a9b', // Muted blue - secondary text\r\n h1: '#f95738', // Tomato - h1 headers\r\n h2: '#ee964b', // Sandy Brown - h2 headers\r\n h3: '#3d8a51', // Forest green - h3 headers\r\n strong: '#ee964b', // Sandy Brown - bold text\r\n em: '#f95738', // Tomato - italic text\r\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\r\n link: '#0d3b66', // Yale Blue - links\r\n code: '#0d3b66', // Yale Blue - inline code\r\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\r\n blockquote: '#5a7a9b', // Muted blue - blockquotes\r\n hr: '#5a7a9b', // Muted blue - horizontal rules\r\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\r\n syntax: '#999999', // Gray - syntax highlighting fallback\r\n cursor: '#f95738', // Tomato - cursor\r\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\r\n listMarker: '#ee964b', // Sandy Brown - list markers\r\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\r\n border: '#e0e0e0', // Light gray - borders\r\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\r\n primary: '#0d3b66', // Yale Blue - primary accent\r\n // Toolbar colors\r\n toolbarBg: '#ffffff', // White - toolbar background\r\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\r\n toolbarHover: '#f5f5f5', // Light gray - hover background\r\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\r\n }\r\n};\r\n\r\n/**\r\n * Cave theme - Dark ocean depths\r\n */\r\nexport const cave = {\r\n name: 'cave',\r\n colors: {\r\n bgPrimary: '#141E26', // Deep ocean - main background\r\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\r\n text: '#c5dde8', // Light blue-gray - main text\r\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\r\n textSecondary: '#9fcfec', // Brighter blue - secondary text\r\n h1: '#d4a5ff', // Rich lavender - h1 headers\r\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\r\n h3: '#9fcfec', // Brighter blue - h3 headers\r\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\r\n em: '#9fcfec', // Brighter blue - italic text\r\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\r\n link: '#9fcfec', // Brighter blue - links\r\n code: '#c5dde8', // Light blue-gray - inline code\r\n codeBg: '#1a232b', // Very dark blue - code background\r\n blockquote: '#9fcfec', // Brighter blue - same as italic\r\n hr: '#c5dde8', // Light blue-gray - horizontal rules\r\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\r\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\r\n cursor: '#f26419', // Orange Pantone - cursor\r\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\r\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\r\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\r\n border: '#2a3f52', // Dark blue-gray - borders\r\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\r\n primary: '#9fcfec', // Brighter blue - primary accent\r\n // Toolbar colors for dark theme\r\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\r\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\r\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\r\n toolbarActive: '#2a3f52', // Even lighter - active button background\r\n }\r\n};\r\n\r\n/**\r\n * Auto theme - Automatically switches between solar and cave based on system preference\r\n * This is a special marker theme that triggers automatic theme switching\r\n */\r\nexport const auto = {\r\n name: 'auto',\r\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\r\n colors: solar.colors // Default to solar colors for initial render\r\n};\r\n\r\n/**\r\n * Default themes registry\r\n */\r\nexport const themes = {\r\n solar,\r\n cave,\r\n auto,\r\n // Aliases for backward compatibility\r\n light: solar,\r\n dark: cave\r\n};\r\n\r\n/**\r\n * Get theme by name or return custom theme object\r\n * @param {string|Object} theme - Theme name or custom theme object\r\n * @returns {Object} Theme configuration\r\n */\r\nexport function getTheme(theme) {\r\n if (typeof theme === 'string') {\r\n const themeObj = themes[theme] || themes.solar;\r\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\r\n return { ...themeObj, name: theme };\r\n }\r\n return theme;\r\n}\r\n\r\n/**\r\n * Resolve auto theme to actual theme based on system color scheme preference\r\n * @param {string} themeName - Theme name to resolve\r\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\r\n */\r\nexport function resolveAutoTheme(themeName) {\r\n if (themeName !== 'auto') {\r\n return themeName;\r\n }\r\n\r\n // Check for system dark mode preference\r\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n return isDarkMode ? 'cave' : 'solar';\r\n}\r\n\r\n/**\r\n * Get the current system color scheme preference\r\n * @returns {string} 'dark' or 'light'\r\n */\r\nexport function getSystemColorScheme() {\r\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n return isDarkMode ? 'dark' : 'light';\r\n}\r\n\r\n/**\r\n * Apply theme colors to CSS variables\r\n * @param {Object} colors - Theme colors object\r\n * @returns {string} CSS custom properties string\r\n */\r\nexport function themeToCSSVars(colors) {\r\n const vars = [];\r\n for (const [key, value] of Object.entries(colors)) {\r\n // Convert camelCase to kebab-case\r\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n vars.push(`--${varName}: ${value};`);\r\n }\r\n return vars.join('\\n');\r\n}\r\n\r\n/**\r\n * Merge custom colors with base theme\r\n * @param {Object} baseTheme - Base theme object\r\n * @param {Object} customColors - Custom color overrides\r\n * @returns {Object} Merged theme object\r\n */\r\nexport function mergeTheme(baseTheme, customColors = {}) {\r\n return {\r\n ...baseTheme,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customColors\r\n }\r\n };\r\n}", "/**\r\n * CSS styles for OverType editor\r\n * Embedded in JavaScript to ensure single-file distribution\r\n */\r\n\r\nimport { themeToCSSVars } from './themes.js';\r\n\r\n/**\r\n * Generate the complete CSS for the editor\r\n * @param {Object} options - Configuration options\r\n * @returns {string} Complete CSS string\r\n */\r\nexport function generateStyles(options = {}) {\r\n const {\r\n fontSize = '14px',\r\n lineHeight = 1.6,\r\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\r\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\r\n padding = '20px',\r\n theme = null,\r\n mobile = {}\r\n } = options;\r\n\r\n // Generate mobile overrides\r\n const mobileStyles = Object.keys(mobile).length > 0 ? `\r\n @media (max-width: 640px) {\r\n .overtype-wrapper .overtype-input,\r\n .overtype-wrapper .overtype-preview {\r\n ${Object.entries(mobile)\r\n .map(([prop, val]) => {\r\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n return `${cssProp}: ${val} !important;`;\r\n })\r\n .join('\\n ')}\r\n }\r\n }\r\n ` : '';\r\n\r\n // Generate theme variables if provided\r\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\r\n\r\n return `\r\n /* OverType Editor Styles */\r\n \r\n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\r\n .overtype-container * {\r\n /* Box model - these commonly leak */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: 0 !important;\r\n \r\n /* Layout - these can break our layout */\r\n /* Don't reset position - it breaks dropdowns */\r\n float: none !important;\r\n clear: none !important;\r\n \r\n /* Typography - only reset decorative aspects */\r\n text-decoration: none !important;\r\n text-transform: none !important;\r\n letter-spacing: normal !important;\r\n \r\n /* Visual effects that can interfere */\r\n box-shadow: none !important;\r\n text-shadow: none !important;\r\n \r\n /* Ensure box-sizing is consistent */\r\n box-sizing: border-box !important;\r\n \r\n /* Keep inheritance for these */\r\n /* font-family, color, line-height, font-size - inherit */\r\n }\r\n \r\n /* Container base styles after reset */\r\n .overtype-container {\r\n display: flex !important;\r\n flex-direction: column !important;\r\n width: 100% !important;\r\n height: 100% !important;\r\n position: relative !important; /* Override reset - needed for absolute children */\r\n overflow: visible !important; /* Allow dropdown to overflow container */\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\r\n text-align: left !important;\r\n ${themeVars ? `\r\n /* Theme Variables */\r\n ${themeVars}` : ''}\r\n }\r\n \r\n /* Force left alignment for all elements in the editor */\r\n .overtype-container .overtype-wrapper * {\r\n text-align: left !important;\r\n }\r\n \r\n /* Auto-resize mode styles */\r\n .overtype-container.overtype-auto-resize {\r\n height: auto !important;\r\n }\r\n\r\n .overtype-container.overtype-auto-resize .overtype-wrapper {\r\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\r\n height: auto !important;\r\n min-height: 60px !important;\r\n overflow: visible !important;\r\n }\r\n \r\n .overtype-wrapper {\r\n position: relative !important; /* Override reset - needed for absolute children */\r\n width: 100% !important;\r\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\r\n min-height: 60px !important; /* Minimum usable height */\r\n overflow: hidden !important;\r\n background: var(--bg-secondary, #ffffff) !important;\r\n z-index: 1; /* Below toolbar and dropdown */\r\n }\r\n\r\n /* Critical alignment styles - must be identical for both layers */\r\n .overtype-wrapper .overtype-input,\r\n .overtype-wrapper .overtype-preview {\r\n /* Positioning - must be identical */\r\n position: absolute !important; /* Override reset - required for overlay */\r\n top: 0 !important;\r\n left: 0 !important;\r\n width: 100% !important;\r\n height: 100% !important;\r\n \r\n /* Font properties - any difference breaks alignment */\r\n font-family: ${fontFamily} !important;\r\n font-variant-ligatures: none !important; /* keep metrics stable for code */\r\n font-size: var(--instance-font-size, ${fontSize}) !important;\r\n line-height: var(--instance-line-height, ${lineHeight}) !important;\r\n font-weight: normal !important;\r\n font-style: normal !important;\r\n font-variant: normal !important;\r\n font-stretch: normal !important;\r\n font-kerning: none !important;\r\n font-feature-settings: normal !important;\r\n \r\n /* Box model - must match exactly */\r\n padding: var(--instance-padding, ${padding}) !important;\r\n margin: 0 !important;\r\n border: none !important;\r\n outline: none !important;\r\n box-sizing: border-box !important;\r\n \r\n /* Text layout - critical for character positioning */\r\n white-space: pre-wrap !important;\r\n word-wrap: break-word !important;\r\n word-break: normal !important;\r\n overflow-wrap: break-word !important;\r\n tab-size: 2 !important;\r\n -moz-tab-size: 2 !important;\r\n text-align: left !important;\r\n text-indent: 0 !important;\r\n letter-spacing: normal !important;\r\n word-spacing: normal !important;\r\n \r\n /* Text rendering */\r\n text-transform: none !important;\r\n text-rendering: auto !important;\r\n -webkit-font-smoothing: auto !important;\r\n -webkit-text-size-adjust: 100% !important;\r\n \r\n /* Direction and writing */\r\n direction: ltr !important;\r\n writing-mode: horizontal-tb !important;\r\n unicode-bidi: normal !important;\r\n text-orientation: mixed !important;\r\n \r\n /* Visual effects that could shift perception */\r\n text-shadow: none !important;\r\n filter: none !important;\r\n transform: none !important;\r\n zoom: 1 !important;\r\n \r\n /* Vertical alignment */\r\n vertical-align: baseline !important;\r\n \r\n /* Size constraints */\r\n min-width: 0 !important;\r\n min-height: 0 !important;\r\n max-width: none !important;\r\n max-height: none !important;\r\n \r\n /* Overflow */\r\n overflow-y: auto !important;\r\n overflow-x: auto !important;\r\n /* overscroll-behavior removed to allow scroll-through to parent */\r\n scrollbar-width: auto !important;\r\n scrollbar-gutter: auto !important;\r\n \r\n /* Animation/transition - disabled to prevent movement */\r\n animation: none !important;\r\n transition: none !important;\r\n }\r\n\r\n /* Input layer styles */\r\n .overtype-wrapper .overtype-input {\r\n /* Layer positioning */\r\n z-index: 1 !important;\r\n \r\n /* Text visibility */\r\n color: transparent !important;\r\n caret-color: var(--cursor, #f95738) !important;\r\n background-color: transparent !important;\r\n \r\n /* Textarea-specific */\r\n resize: none !important;\r\n appearance: none !important;\r\n -webkit-appearance: none !important;\r\n -moz-appearance: none !important;\r\n \r\n /* Prevent mobile zoom on focus */\r\n touch-action: manipulation !important;\r\n \r\n /* Disable autofill and spellcheck */\r\n autocomplete: off !important;\r\n autocorrect: off !important;\r\n autocapitalize: off !important;\r\n spellcheck: false !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-input::selection {\r\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\r\n }\r\n\r\n /* Preview layer styles */\r\n .overtype-wrapper .overtype-preview {\r\n /* Layer positioning */\r\n z-index: 0 !important;\r\n pointer-events: none !important;\r\n color: var(--text, #0d3b66) !important;\r\n background-color: transparent !important;\r\n \r\n /* Prevent text selection */\r\n user-select: none !important;\r\n -webkit-user-select: none !important;\r\n -moz-user-select: none !important;\r\n -ms-user-select: none !important;\r\n }\r\n\r\n /* Defensive styles for preview child divs */\r\n .overtype-wrapper .overtype-preview div {\r\n /* Reset any inherited styles */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: none !important;\r\n text-align: left !important;\r\n text-indent: 0 !important;\r\n display: block !important;\r\n position: static !important;\r\n transform: none !important;\r\n min-height: 0 !important;\r\n max-height: none !important;\r\n line-height: inherit !important;\r\n font-size: inherit !important;\r\n font-family: inherit !important;\r\n }\r\n\r\n /* Markdown element styling - NO SIZE CHANGES */\r\n .overtype-wrapper .overtype-preview .header {\r\n font-weight: bold !important;\r\n }\r\n\r\n /* Header colors */\r\n .overtype-wrapper .overtype-preview .h1 { \r\n color: var(--h1, #f95738) !important; \r\n }\r\n .overtype-wrapper .overtype-preview .h2 { \r\n color: var(--h2, #ee964b) !important; \r\n }\r\n .overtype-wrapper .overtype-preview .h3 { \r\n color: var(--h3, #3d8a51) !important; \r\n }\r\n\r\n /* Semantic headers - flatten in edit mode */\r\n .overtype-wrapper .overtype-preview h1,\r\n .overtype-wrapper .overtype-preview h2,\r\n .overtype-wrapper .overtype-preview h3 {\r\n font-size: inherit !important;\r\n font-weight: bold !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n display: inline !important;\r\n line-height: inherit !important;\r\n }\r\n\r\n /* Header colors for semantic headers */\r\n .overtype-wrapper .overtype-preview h1 { \r\n color: var(--h1, #f95738) !important; \r\n }\r\n .overtype-wrapper .overtype-preview h2 { \r\n color: var(--h2, #ee964b) !important; \r\n }\r\n .overtype-wrapper .overtype-preview h3 { \r\n color: var(--h3, #3d8a51) !important; \r\n }\r\n\r\n /* Lists - remove styling in edit mode */\r\n .overtype-wrapper .overtype-preview ul,\r\n .overtype-wrapper .overtype-preview ol {\r\n list-style: none !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n display: block !important; /* Lists need to be block for line breaks */\r\n }\r\n\r\n .overtype-wrapper .overtype-preview li {\r\n display: block !important; /* Each item on its own line */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n /* Don't set list-style here - let ul/ol control it */\r\n }\r\n\r\n /* Bold text */\r\n .overtype-wrapper .overtype-preview strong {\r\n color: var(--strong, #ee964b) !important;\r\n font-weight: bold !important;\r\n }\r\n\r\n /* Italic text */\r\n .overtype-wrapper .overtype-preview em {\r\n color: var(--em, #f95738) !important;\r\n text-decoration-color: var(--em, #f95738) !important;\r\n text-decoration-thickness: 1px !important;\r\n font-style: italic !important;\r\n }\r\n\r\n /* Strikethrough text */\r\n .overtype-wrapper .overtype-preview del {\r\n color: var(--del, #ee964b) !important;\r\n text-decoration: line-through !important;\r\n text-decoration-color: var(--del, #ee964b) !important;\r\n text-decoration-thickness: 1px !important;\r\n }\r\n\r\n /* Inline code */\r\n .overtype-wrapper .overtype-preview code {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n color: var(--code, #0d3b66) !important;\r\n padding: 0 !important;\r\n border-radius: 2px !important;\r\n font-family: inherit !important;\r\n font-size: inherit !important;\r\n line-height: inherit !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Code blocks - consolidated pre blocks */\r\n .overtype-wrapper .overtype-preview pre {\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n border-radius: 4px !important;\r\n overflow-x: auto !important;\r\n }\r\n \r\n /* Code block styling in normal mode - yellow background */\r\n .overtype-wrapper .overtype-preview pre.code-block {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\r\n }\r\n\r\n /* Code inside pre blocks - remove background */\r\n .overtype-wrapper .overtype-preview pre code {\r\n background: transparent !important;\r\n color: var(--code, #0d3b66) !important;\r\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\r\n }\r\n\r\n /* Blockquotes */\r\n .overtype-wrapper .overtype-preview .blockquote {\r\n color: var(--blockquote, #5a7a9b) !important;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n border: none !important;\r\n }\r\n\r\n /* Links */\r\n .overtype-wrapper .overtype-preview a {\r\n color: var(--link, #0d3b66) !important;\r\n text-decoration: underline !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-preview a:hover {\r\n text-decoration: underline !important;\r\n color: var(--link, #0d3b66) !important;\r\n }\r\n\r\n /* Lists - no list styling */\r\n .overtype-wrapper .overtype-preview ul,\r\n .overtype-wrapper .overtype-preview ol {\r\n list-style: none !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n\r\n /* Horizontal rules */\r\n .overtype-wrapper .overtype-preview hr {\r\n border: none !important;\r\n color: var(--hr, #5a7a9b) !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-preview .hr-marker {\r\n color: var(--hr, #5a7a9b) !important;\r\n opacity: 0.6 !important;\r\n }\r\n\r\n /* Code fence markers - with background when not in code block */\r\n .overtype-wrapper .overtype-preview .code-fence {\r\n color: var(--code, #0d3b66) !important;\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n }\r\n \r\n /* Code block lines - background for entire code block */\r\n .overtype-wrapper .overtype-preview .code-block-line {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n }\r\n \r\n /* Remove background from code fence when inside code block line */\r\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\r\n background: transparent !important;\r\n }\r\n\r\n /* Raw markdown line */\r\n .overtype-wrapper .overtype-preview .raw-line {\r\n color: var(--raw-line, #5a7a9b) !important;\r\n font-style: normal !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Syntax markers */\r\n .overtype-wrapper .overtype-preview .syntax-marker {\r\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\r\n opacity: 0.7 !important;\r\n }\r\n\r\n /* List markers */\r\n .overtype-wrapper .overtype-preview .list-marker {\r\n color: var(--list-marker, #ee964b) !important;\r\n }\r\n\r\n /* Stats bar */\r\n \r\n /* Stats bar - positioned by flexbox */\r\n .overtype-stats {\r\n height: 40px !important;\r\n padding: 0 20px !important;\r\n background: #f8f9fa !important;\r\n border-top: 1px solid #e0e0e0 !important;\r\n display: flex !important;\r\n justify-content: space-between !important;\r\n align-items: center !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\r\n font-size: 0.85rem !important;\r\n color: #666 !important;\r\n flex-shrink: 0 !important; /* Don't shrink */\r\n z-index: 10001 !important; /* Above link tooltip */\r\n position: relative !important; /* Enable z-index */\r\n }\r\n \r\n /* Dark theme stats bar */\r\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\r\n background: var(--bg-secondary, #1D2D3E) !important;\r\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\r\n color: var(--text, #c5dde8) !important;\r\n }\r\n \r\n .overtype-stats .overtype-stat {\r\n display: flex !important;\r\n align-items: center !important;\r\n gap: 5px !important;\r\n white-space: nowrap !important;\r\n }\r\n \r\n .overtype-stats .live-dot {\r\n width: 8px !important;\r\n height: 8px !important;\r\n background: #4caf50 !important;\r\n border-radius: 50% !important;\r\n animation: overtype-pulse 2s infinite !important;\r\n }\r\n \r\n @keyframes overtype-pulse {\r\n 0%, 100% { opacity: 1; transform: scale(1); }\r\n 50% { opacity: 0.6; transform: scale(1.2); }\r\n }\r\n \r\n\r\n /* Toolbar Styles */\r\n .overtype-toolbar {\r\n display: flex !important;\r\n align-items: center !important;\r\n gap: 4px !important;\r\n padding: 8px !important; /* Override reset */\r\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\r\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\r\n overflow-x: auto !important; /* Allow horizontal scrolling */\r\n overflow-y: hidden !important; /* Hide vertical overflow */\r\n -webkit-overflow-scrolling: touch !important;\r\n flex-shrink: 0 !important;\r\n height: auto !important;\r\n position: relative !important; /* Override reset */\r\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\r\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\r\n }\r\n \r\n /* Thin scrollbar styling */\r\n .overtype-toolbar::-webkit-scrollbar {\r\n height: 4px;\r\n }\r\n \r\n .overtype-toolbar::-webkit-scrollbar-track {\r\n background: transparent;\r\n }\r\n \r\n .overtype-toolbar::-webkit-scrollbar-thumb {\r\n background: rgba(0, 0, 0, 0.2);\r\n border-radius: 2px;\r\n }\r\n\r\n .overtype-toolbar-button {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 6px;\r\n background: transparent;\r\n color: var(--toolbar-icon, var(--text-secondary, #666));\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n\r\n .overtype-toolbar-button svg {\r\n width: 20px;\r\n height: 20px;\r\n fill: currentColor;\r\n }\r\n\r\n .overtype-toolbar-button:hover {\r\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\r\n color: var(--toolbar-icon, var(--text-primary, #333));\r\n }\r\n\r\n .overtype-toolbar-button:active {\r\n transform: scale(0.95);\r\n }\r\n\r\n .overtype-toolbar-button.active {\r\n background: var(--toolbar-active, var(--primary, #007bff));\r\n color: var(--toolbar-icon, var(--text-primary, #333));\r\n }\r\n\r\n .overtype-toolbar-button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .overtype-toolbar-separator {\r\n width: 1px;\r\n height: 24px;\r\n background: var(--border, #e0e0e0);\r\n margin: 0 4px;\r\n flex-shrink: 0;\r\n }\r\n\r\n /* Adjust wrapper when toolbar is present */\r\n /* Mobile toolbar adjustments */\r\n @media (max-width: 640px) {\r\n .overtype-toolbar {\r\n padding: 6px;\r\n gap: 2px;\r\n }\r\n\r\n .overtype-toolbar-button {\r\n width: 36px;\r\n height: 36px;\r\n }\r\n\r\n .overtype-toolbar-separator {\r\n margin: 0 2px;\r\n }\r\n }\r\n \r\n /* Plain mode - hide preview and show textarea text */\r\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\r\n display: none !important;\r\n }\r\n \r\n .overtype-container[data-mode=\"plain\"] .overtype-input {\r\n color: var(--text, #0d3b66) !important;\r\n /* Use system font stack for better plain text readability */\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \r\n \"Helvetica Neue\", Arial, sans-serif !important;\r\n }\r\n \r\n /* Ensure textarea remains transparent in overlay mode */\r\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\r\n color: transparent !important;\r\n }\r\n\r\n /* Dropdown menu styles */\r\n .overtype-toolbar-button {\r\n position: relative !important; /* Override reset - needed for dropdown */\r\n }\r\n\r\n .overtype-toolbar-button.dropdown-active {\r\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\r\n }\r\n\r\n .overtype-dropdown-menu {\r\n position: fixed !important; /* Fixed positioning relative to viewport */\r\n background: var(--bg-secondary, white) !important; /* Override reset */\r\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\r\n border-radius: 6px;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\r\n z-index: 10000; /* Very high z-index to ensure visibility */\r\n min-width: 150px;\r\n padding: 4px 0 !important; /* Override reset */\r\n /* Position will be set via JavaScript based on button position */\r\n }\r\n\r\n .overtype-dropdown-item {\r\n display: flex;\r\n align-items: center;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: none;\r\n background: none;\r\n text-align: left;\r\n cursor: pointer;\r\n font-size: 14px;\r\n color: var(--text, #333);\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\r\n }\r\n\r\n .overtype-dropdown-item:hover {\r\n background: var(--hover-bg, #f0f0f0);\r\n }\r\n\r\n .overtype-dropdown-item.active {\r\n font-weight: 600;\r\n }\r\n\r\n .overtype-dropdown-check {\r\n width: 16px;\r\n margin-right: 8px;\r\n color: var(--h1, #007bff);\r\n }\r\n\r\n .overtype-dropdown-icon {\r\n width: 20px;\r\n margin-right: 8px;\r\n text-align: center;\r\n }\r\n\r\n /* Preview mode styles */\r\n .overtype-container[data-mode=\"preview\"] .overtype-input {\r\n display: none !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\r\n pointer-events: auto !important;\r\n user-select: text !important;\r\n cursor: text !important;\r\n }\r\n\r\n /* Hide syntax markers in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\r\n display: none !important;\r\n }\r\n \r\n /* Hide URL part of links in preview mode - extra specificity */\r\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\r\n .overtype-container[data-mode=\"preview\"] .url-part {\r\n display: none !important;\r\n }\r\n \r\n /* Hide all syntax markers inside links too */\r\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\r\n display: none !important;\r\n }\r\n\r\n /* Headers - restore proper sizing in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\r\n font-weight: 600 !important;\r\n margin: 0 !important;\r\n display: block !important;\r\n color: inherit !important; /* Use parent text color */\r\n line-height: 1 !important; /* Tight line height for headings */\r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \r\n font-size: 2em !important; \r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \r\n font-size: 1.5em !important; \r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \r\n font-size: 1.17em !important; \r\n }\r\n\r\n /* Lists - restore list styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\r\n display: block !important;\r\n list-style: disc !important;\r\n padding-left: 2em !important;\r\n margin: 1em 0 !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\r\n display: block !important;\r\n list-style: decimal !important;\r\n padding-left: 2em !important;\r\n margin: 1em 0 !important;\r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\r\n display: list-item !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n /* Task list checkboxes - only in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\r\n list-style: none !important;\r\n position: relative !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\r\n margin-right: 0.5em !important;\r\n cursor: default !important;\r\n vertical-align: middle !important;\r\n }\r\n\r\n /* Task list in normal mode - keep syntax visible */\r\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\r\n list-style: none !important;\r\n }\r\n\r\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\r\n color: var(--syntax, #999999) !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Links - make clickable in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\r\n pointer-events: auto !important;\r\n cursor: pointer !important;\r\n color: var(--link, #0066cc) !important;\r\n text-decoration: underline !important;\r\n }\r\n\r\n /* Code blocks - proper pre/code styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\r\n background: #2d2d2d !important;\r\n color: #f8f8f2 !important;\r\n padding: 1.2em !important;\r\n border-radius: 3px !important;\r\n overflow-x: auto !important;\r\n margin: 0 !important;\r\n display: block !important;\r\n }\r\n \r\n /* Cave theme code block background in preview mode */\r\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\r\n background: #11171F !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\r\n background: transparent !important;\r\n color: inherit !important;\r\n padding: 0 !important;\r\n font-family: ${fontFamily} !important;\r\n font-size: 0.9em !important;\r\n line-height: 1.4 !important;\r\n }\r\n\r\n /* Hide old code block lines and fences in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\r\n display: none !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\r\n display: none !important;\r\n }\r\n\r\n /* Blockquotes - enhanced styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\r\n display: block !important;\r\n border-left: 4px solid var(--blockquote, #ddd) !important;\r\n padding-left: 1em !important;\r\n margin: 1em 0 !important;\r\n font-style: italic !important;\r\n }\r\n\r\n /* Typography improvements in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\r\n font-family: Georgia, 'Times New Roman', serif !important;\r\n font-size: 16px !important;\r\n line-height: 1.8 !important;\r\n color: var(--text, #333) !important; /* Consistent text color */\r\n }\r\n\r\n /* Inline code in preview mode - keep monospace */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\r\n font-family: ${fontFamily} !important;\r\n font-size: 0.9em !important;\r\n background: rgba(135, 131, 120, 0.15) !important;\r\n padding: 0.2em 0.4em !important;\r\n border-radius: 3px !important;\r\n }\r\n\r\n /* Strong and em elements in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\r\n font-weight: 700 !important;\r\n color: inherit !important; /* Use parent text color */\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\r\n font-style: italic !important;\r\n color: inherit !important; /* Use parent text color */\r\n }\r\n\r\n /* HR in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\r\n display: block !important;\r\n border-top: 2px solid var(--hr, #ddd) !important;\r\n text-indent: -9999px !important;\r\n height: 2px !important;\r\n }\r\n\r\n /* Link Tooltip - Base styles (all browsers) */\r\n .overtype-link-tooltip {\r\n /* Visual styles that work for both positioning methods */\r\n background: #333 !important;\r\n color: white !important;\r\n padding: 6px 10px !important;\r\n border-radius: 16px !important;\r\n font-size: 12px !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\r\n display: none !important;\r\n z-index: 10000 !important;\r\n cursor: pointer !important;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\r\n max-width: 300px !important;\r\n white-space: nowrap !important;\r\n overflow: hidden !important;\r\n text-overflow: ellipsis !important;\r\n\r\n /* Base positioning for Floating UI fallback */\r\n position: absolute;\r\n }\r\n\r\n .overtype-link-tooltip.visible {\r\n display: flex !important;\r\n }\r\n\r\n /* CSS Anchor Positioning (modern browsers only) */\r\n @supports (position-anchor: --x) and (position-area: center) {\r\n .overtype-link-tooltip {\r\n /* Only anchor positioning specific properties */\r\n position-anchor: var(--target-anchor, --link-0);\r\n position-area: block-end center;\r\n margin-top: 8px !important;\r\n position-try: most-width block-end inline-end, flip-inline, block-start center;\r\n position-visibility: anchors-visible;\r\n }\r\n }\r\n\r\n ${mobileStyles}\r\n `;\r\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\r\n * Toolbar component for OverType editor\r\n * Provides markdown formatting buttons with support for custom buttons\r\n */\r\n\r\nimport * as markdownActions from 'markdown-actions';\r\n\r\nexport class Toolbar {\r\n constructor(editor, options = {}) {\r\n this.editor = editor;\r\n this.container = null;\r\n this.buttons = {};\r\n\r\n // Get toolbar buttons array\r\n this.toolbarButtons = options.toolbarButtons || [];\r\n }\r\n\r\n /**\r\n * Create and render toolbar\r\n */\r\n create() {\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-toolbar';\r\n this.container.setAttribute('role', 'toolbar');\r\n this.container.setAttribute('aria-label', 'Formatting toolbar');\r\n\r\n // Create buttons from toolbarButtons array\r\n this.toolbarButtons.forEach(buttonConfig => {\r\n if (buttonConfig.name === 'separator') {\r\n const separator = this.createSeparator();\r\n this.container.appendChild(separator);\r\n } else {\r\n const button = this.createButton(buttonConfig);\r\n this.buttons[buttonConfig.name] = button;\r\n this.container.appendChild(button);\r\n }\r\n });\r\n\r\n // Insert toolbar before the wrapper (as sibling, not child)\r\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\r\n }\r\n\r\n /**\r\n * Create a toolbar separator\r\n */\r\n createSeparator() {\r\n const separator = document.createElement('div');\r\n separator.className = 'overtype-toolbar-separator';\r\n separator.setAttribute('role', 'separator');\r\n return separator;\r\n }\r\n\r\n /**\r\n * Create a toolbar button\r\n */\r\n createButton(buttonConfig) {\r\n const button = document.createElement('button');\r\n button.className = 'overtype-toolbar-button';\r\n button.type = 'button';\r\n button.setAttribute('data-button', buttonConfig.name);\r\n button.title = buttonConfig.title || '';\r\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\r\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\r\n\r\n // Special handling for viewMode dropdown\r\n if (buttonConfig.name === 'viewMode') {\r\n button.classList.add('has-dropdown');\r\n button.dataset.dropdown = 'true';\r\n button.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n this.toggleViewModeDropdown(button);\r\n });\r\n return button;\r\n }\r\n\r\n // Standard button click handler - delegate to performAction\r\n button._clickHandler = (e) => {\r\n e.preventDefault();\r\n const actionId = buttonConfig.actionId || buttonConfig.name;\r\n this.editor.performAction(actionId, e);\r\n };\r\n\r\n button.addEventListener('click', button._clickHandler);\r\n return button;\r\n }\r\n\r\n /**\r\n * Handle button action programmatically\r\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\r\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\r\n * @returns {Promise} Whether the action was executed\r\n */\r\n async handleAction(actionIdOrConfig) {\r\n // Old style: buttonConfig object with .action function - execute directly\r\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\r\n this.editor.textarea.focus();\r\n try {\r\n await actionIdOrConfig.action({\r\n editor: this.editor,\r\n getValue: () => this.editor.getValue(),\r\n setValue: (value) => this.editor.setValue(value),\r\n event: null\r\n });\r\n return true;\r\n } catch (error) {\r\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\r\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\r\n detail: { buttonName: actionIdOrConfig.name, error }\r\n }));\r\n return false;\r\n }\r\n }\r\n\r\n // New style: string actionId - delegate to performAction\r\n if (typeof actionIdOrConfig === 'string') {\r\n return this.editor.performAction(actionIdOrConfig, null);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Sanitize SVG to prevent XSS\r\n */\r\n sanitizeSVG(svg) {\r\n if (typeof svg !== 'string') return '';\r\n\r\n // Remove script tags and on* event handlers\r\n const cleaned = svg\r\n .replace(/)<[^<]*)*<\\/script>/gi, '')\r\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\r\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\r\n\r\n return cleaned;\r\n }\r\n\r\n /**\r\n * Toggle view mode dropdown (internal implementation)\r\n * Not exposed to users - viewMode button behavior is fixed\r\n */\r\n toggleViewModeDropdown(button) {\r\n // Close any existing dropdown\r\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\r\n if (existingDropdown) {\r\n existingDropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n return;\r\n }\r\n\r\n button.classList.add('dropdown-active');\r\n\r\n const dropdown = this.createViewModeDropdown(button);\r\n\r\n // Position dropdown relative to button\r\n const rect = button.getBoundingClientRect();\r\n dropdown.style.position = 'absolute';\r\n dropdown.style.top = `${rect.bottom + 5}px`;\r\n dropdown.style.left = `${rect.left}px`;\r\n\r\n document.body.appendChild(dropdown);\r\n\r\n // Click outside to close\r\n this.handleDocumentClick = (e) => {\r\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\r\n dropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n }\r\n };\r\n\r\n setTimeout(() => {\r\n document.addEventListener('click', this.handleDocumentClick);\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Create view mode dropdown menu (internal implementation)\r\n */\r\n createViewModeDropdown(button) {\r\n const dropdown = document.createElement('div');\r\n dropdown.className = 'overtype-dropdown-menu';\r\n\r\n const items = [\r\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\r\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\r\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\r\n ];\r\n\r\n const currentMode = this.editor.container.dataset.mode || 'normal';\r\n\r\n items.forEach(item => {\r\n const menuItem = document.createElement('button');\r\n menuItem.className = 'overtype-dropdown-item';\r\n menuItem.type = 'button';\r\n menuItem.textContent = item.label;\r\n\r\n if (item.id === currentMode) {\r\n menuItem.classList.add('active');\r\n menuItem.setAttribute('aria-current', 'true');\r\n const checkmark = document.createElement('span');\r\n checkmark.className = 'overtype-dropdown-icon';\r\n checkmark.textContent = item.icon;\r\n menuItem.prepend(checkmark);\r\n }\r\n\r\n menuItem.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n\r\n // Handle view mode changes\r\n switch(item.id) {\r\n case 'plain':\r\n this.editor.showPlainTextarea();\r\n break;\r\n case 'preview':\r\n this.editor.showPreviewMode();\r\n break;\r\n case 'normal':\r\n default:\r\n this.editor.showNormalEditMode();\r\n break;\r\n }\r\n\r\n dropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n });\r\n\r\n dropdown.appendChild(menuItem);\r\n });\r\n\r\n return dropdown;\r\n }\r\n\r\n /**\r\n * Update active states of toolbar buttons\r\n */\r\n updateButtonStates() {\r\n try {\r\n const activeFormats = markdownActions.getActiveFormats?.(\r\n this.editor.textarea,\r\n this.editor.textarea.selectionStart\r\n ) || [];\r\n\r\n Object.entries(this.buttons).forEach(([name, button]) => {\r\n if (name === 'viewMode') return; // Skip dropdown button\r\n\r\n let isActive = false;\r\n\r\n switch(name) {\r\n case 'bold':\r\n isActive = activeFormats.includes('bold');\r\n break;\r\n case 'italic':\r\n isActive = activeFormats.includes('italic');\r\n break;\r\n case 'code':\r\n isActive = false; // Disabled: unreliable in code blocks\r\n break;\r\n case 'bulletList':\r\n isActive = activeFormats.includes('bullet-list');\r\n break;\r\n case 'orderedList':\r\n isActive = activeFormats.includes('numbered-list');\r\n break;\r\n case 'taskList':\r\n isActive = activeFormats.includes('task-list');\r\n break;\r\n case 'quote':\r\n isActive = activeFormats.includes('quote');\r\n break;\r\n case 'h1':\r\n isActive = activeFormats.includes('header');\r\n break;\r\n case 'h2':\r\n isActive = activeFormats.includes('header-2');\r\n break;\r\n case 'h3':\r\n isActive = activeFormats.includes('header-3');\r\n break;\r\n }\r\n\r\n button.classList.toggle('active', isActive);\r\n button.setAttribute('aria-pressed', isActive.toString());\r\n });\r\n } catch (error) {\r\n // Silently fail if markdown-actions not available\r\n }\r\n }\r\n\r\n /**\r\n * Destroy toolbar and cleanup\r\n */\r\n destroy() {\r\n if (this.container) {\r\n // Clean up event listeners\r\n if (this.handleDocumentClick) {\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n }\r\n\r\n // Clean up button listeners\r\n Object.values(this.buttons).forEach(button => {\r\n if (button._clickHandler) {\r\n button.removeEventListener('click', button._clickHandler);\r\n delete button._clickHandler;\r\n }\r\n });\r\n\r\n // Remove container\r\n this.container.remove();\r\n this.container = null;\r\n this.buttons = {};\r\n }\r\n }\r\n}\r\n", "/**\r\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\r\n * Shows a clickable tooltip when cursor is within a link\r\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\r\n */\r\n\r\nexport class LinkTooltip {\r\n constructor(editor) {\r\n this.editor = editor;\r\n this.tooltip = null;\r\n this.currentLink = null;\r\n this.hideTimeout = null;\r\n this.visibilityChangeHandler = null;\r\n this.useFloatingUI = false;\r\n this.floatingUI = null;\r\n this.isTooltipHovered = false;\r\n\r\n this.init();\r\n }\r\n\r\n async init() {\r\n // Detect CSS anchor positioning support\r\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\r\n CSS.supports('position-area: center');\r\n\r\n // Load Floating UI if needed\r\n if (!supportsAnchorPositioning) {\r\n try {\r\n // Use indirect eval to prevent bundler from processing the import\r\n const importFn = new Function('url', 'return import(url)');\r\n const { computePosition, offset, shift, flip } = await importFn(\r\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\r\n );\r\n this.floatingUI = { computePosition, offset, shift, flip };\r\n this.useFloatingUI = true;\r\n } catch (error) {\r\n // If dynamic import fails, tooltips simply won't show\r\n console.warn('Failed to load Floating UI fallback:', error);\r\n this.floatingUI = null;\r\n this.useFloatingUI = false;\r\n }\r\n }\r\n\r\n // Create tooltip element\r\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\r\n this.createTooltip();\r\n\r\n // Listen for cursor position changes\r\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\r\n this.editor.textarea.addEventListener('keyup', e => {\r\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\r\n this.checkCursorPosition();\r\n }\r\n });\r\n\r\n // Hide tooltip when typing\r\n this.editor.textarea.addEventListener('input', () => this.hide());\r\n\r\n // Reposition or hide tooltip when scrolling\r\n this.editor.textarea.addEventListener('scroll', () => {\r\n if (this.useFloatingUI && this.currentLink) {\r\n // Reposition the tooltip for Floating UI\r\n this.showWithFloatingUI(this.currentLink);\r\n } else {\r\n // Hide for CSS anchor positioning (native browser behavior handles this)\r\n this.hide();\r\n }\r\n });\r\n\r\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\r\n this.editor.textarea.addEventListener('blur', () => {\r\n if (!this.isTooltipHovered) {\r\n this.hide();\r\n }\r\n });\r\n\r\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\r\n this.visibilityChangeHandler = () => {\r\n if (document.hidden) {\r\n this.hide();\r\n }\r\n };\r\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\r\n\r\n // Track hover state to prevent hiding when clicking tooltip\r\n this.tooltip.addEventListener('mouseenter', () => {\r\n this.isTooltipHovered = true;\r\n this.cancelHide();\r\n });\r\n this.tooltip.addEventListener('mouseleave', () => {\r\n this.isTooltipHovered = false;\r\n this.scheduleHide();\r\n });\r\n }\r\n\r\n createTooltip() {\r\n // Create tooltip element\r\n // Styles are now included in the main stylesheet (styles.js)\r\n this.tooltip = document.createElement('div');\r\n this.tooltip.className = 'overtype-link-tooltip';\r\n\r\n // Add link icon and text container\r\n this.tooltip.innerHTML = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n `;\r\n\r\n // Click handler to open link\r\n this.tooltip.addEventListener('click', e => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (this.currentLink) {\r\n window.open(this.currentLink.url, '_blank');\r\n this.hide();\r\n }\r\n });\r\n\r\n // Append tooltip to editor container\r\n this.editor.container.appendChild(this.tooltip);\r\n }\r\n\r\n checkCursorPosition() {\r\n const cursorPos = this.editor.textarea.selectionStart;\r\n const text = this.editor.textarea.value;\r\n\r\n // Find if cursor is within a markdown link\r\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\r\n\r\n if (linkInfo) {\r\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\r\n this.show(linkInfo);\r\n }\r\n } else {\r\n this.scheduleHide();\r\n }\r\n }\r\n\r\n findLinkAtPosition(text, position) {\r\n // Regex to find markdown links: [text](url)\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n let match;\r\n let linkIndex = 0;\r\n\r\n while ((match = linkRegex.exec(text)) !== null) {\r\n const start = match.index;\r\n const end = match.index + match[0].length;\r\n\r\n if (position >= start && position <= end) {\r\n return {\r\n text: match[1],\r\n url: match[2],\r\n index: linkIndex,\r\n start: start,\r\n end: end\r\n };\r\n }\r\n linkIndex++;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n show(linkInfo) {\r\n this.currentLink = linkInfo;\r\n this.cancelHide();\r\n\r\n // Update tooltip content\r\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\r\n urlSpan.textContent = linkInfo.url;\r\n\r\n if (this.useFloatingUI) {\r\n this.showWithFloatingUI(linkInfo);\r\n } else {\r\n this.showWithAnchorPositioning(linkInfo);\r\n }\r\n\r\n this.tooltip.classList.add('visible');\r\n }\r\n\r\n showWithAnchorPositioning(linkInfo) {\r\n // Set the CSS variable to point to the correct anchor\r\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\r\n }\r\n\r\n async showWithFloatingUI(linkInfo) {\r\n // Find the element in preview that corresponds to this link\r\n const anchorElement = this.findAnchorElement(linkInfo.index);\r\n\r\n if (!anchorElement) {\r\n return;\r\n }\r\n\r\n // Check if anchor element is visible and in viewport\r\n const rect = anchorElement.getBoundingClientRect();\r\n if (rect.width === 0 || rect.height === 0) {\r\n return;\r\n }\r\n\r\n try {\r\n // Compute position using Floating UI\r\n const { x, y } = await this.floatingUI.computePosition(\r\n anchorElement,\r\n this.tooltip,\r\n {\r\n placement: 'bottom',\r\n middleware: [\r\n this.floatingUI.offset(8),\r\n this.floatingUI.shift({ padding: 8 }),\r\n this.floatingUI.flip()\r\n ]\r\n }\r\n );\r\n\r\n // Apply position\r\n Object.assign(this.tooltip.style, {\r\n left: `${x}px`,\r\n top: `${y}px`,\r\n position: 'absolute'\r\n });\r\n } catch (error) {\r\n // If Floating UI computation fails, don't show tooltip\r\n console.warn('Floating UI positioning failed:', error);\r\n return;\r\n }\r\n }\r\n\r\n findAnchorElement(linkIndex) {\r\n // Find the element with the matching anchor-name style\r\n const preview = this.editor.preview;\r\n // Direct query for the specific link - more efficient than iterating\r\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\r\n }\r\n\r\n hide() {\r\n this.tooltip.classList.remove('visible');\r\n this.currentLink = null;\r\n this.isTooltipHovered = false;\r\n }\r\n\r\n scheduleHide() {\r\n this.cancelHide();\r\n this.hideTimeout = setTimeout(() => this.hide(), 300);\r\n }\r\n\r\n cancelHide() {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n this.hideTimeout = null;\r\n }\r\n }\r\n\r\n destroy() {\r\n this.cancelHide();\r\n\r\n // Remove visibility change listener\r\n if (this.visibilityChangeHandler) {\r\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\r\n this.visibilityChangeHandler = null;\r\n }\r\n\r\n if (this.tooltip && this.tooltip.parentNode) {\r\n this.tooltip.parentNode.removeChild(this.tooltip);\r\n }\r\n this.tooltip = null;\r\n this.currentLink = null;\r\n this.floatingUI = null;\r\n this.useFloatingUI = false;\r\n this.isTooltipHovered = false;\r\n }\r\n}\r\n", "/**\r\n * SVG icons for OverType toolbar\r\n * Quill-style icons with inline styles\r\n */\r\n\r\nexport const boldIcon = `\r\n \r\n \r\n`;\r\n\r\nexport const italicIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\nexport const h1Icon = `\r\n \r\n`;\r\n\r\nexport const h2Icon = `\r\n \r\n`;\r\n\r\nexport const h3Icon = `\r\n \r\n`;\r\n\r\nexport const linkIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\nexport const codeIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\n\r\nexport const bulletListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const orderedListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const quoteIcon = `\r\n \r\n \r\n`;\r\n\r\nexport const taskListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const eyeIcon = `\r\n \r\n \r\n`;", "/**\r\n * Toolbar button definitions for OverType editor\r\n * Export built-in buttons that can be used in custom toolbar configurations\r\n */\r\n\r\nimport * as icons from './icons.js';\r\nimport * as markdownActions from 'markdown-actions';\r\n\r\n/**\r\n * Built-in toolbar button definitions\r\n * Each button has: name, actionId, icon, title, action\r\n * - name: DOM identifier for the button element\r\n * - actionId: Canonical action identifier used by performAction\r\n * Action signature: ({ editor, getValue, setValue, event }) => void\r\n */\r\nexport const toolbarButtons = {\r\n bold: {\r\n name: 'bold',\r\n actionId: 'toggleBold',\r\n icon: icons.boldIcon,\r\n title: 'Bold (Ctrl+B)',\r\n action: ({ editor }) => {\r\n markdownActions.toggleBold(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n italic: {\r\n name: 'italic',\r\n actionId: 'toggleItalic',\r\n icon: icons.italicIcon,\r\n title: 'Italic (Ctrl+I)',\r\n action: ({ editor }) => {\r\n markdownActions.toggleItalic(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n code: {\r\n name: 'code',\r\n actionId: 'toggleCode',\r\n icon: icons.codeIcon,\r\n title: 'Inline Code',\r\n action: ({ editor }) => {\r\n markdownActions.toggleCode(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n separator: {\r\n name: 'separator'\r\n // No icon, title, or action - special separator element\r\n },\r\n\r\n link: {\r\n name: 'link',\r\n actionId: 'insertLink',\r\n icon: icons.linkIcon,\r\n title: 'Insert Link',\r\n action: ({ editor }) => {\r\n markdownActions.insertLink(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h1: {\r\n name: 'h1',\r\n actionId: 'toggleH1',\r\n icon: icons.h1Icon,\r\n title: 'Heading 1',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH1(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h2: {\r\n name: 'h2',\r\n actionId: 'toggleH2',\r\n icon: icons.h2Icon,\r\n title: 'Heading 2',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH2(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h3: {\r\n name: 'h3',\r\n actionId: 'toggleH3',\r\n icon: icons.h3Icon,\r\n title: 'Heading 3',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH3(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n bulletList: {\r\n name: 'bulletList',\r\n actionId: 'toggleBulletList',\r\n icon: icons.bulletListIcon,\r\n title: 'Bullet List',\r\n action: ({ editor }) => {\r\n markdownActions.toggleBulletList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n orderedList: {\r\n name: 'orderedList',\r\n actionId: 'toggleNumberedList',\r\n icon: icons.orderedListIcon,\r\n title: 'Numbered List',\r\n action: ({ editor }) => {\r\n markdownActions.toggleNumberedList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n taskList: {\r\n name: 'taskList',\r\n actionId: 'toggleTaskList',\r\n icon: icons.taskListIcon,\r\n title: 'Task List',\r\n action: ({ editor }) => {\r\n if (markdownActions.toggleTaskList) {\r\n markdownActions.toggleTaskList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n }\r\n },\r\n\r\n quote: {\r\n name: 'quote',\r\n actionId: 'toggleQuote',\r\n icon: icons.quoteIcon,\r\n title: 'Quote',\r\n action: ({ editor }) => {\r\n markdownActions.toggleQuote(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n viewMode: {\r\n name: 'viewMode',\r\n icon: icons.eyeIcon,\r\n title: 'View mode'\r\n // Special: handled internally by Toolbar class as dropdown\r\n // No action property - dropdown behavior is internal\r\n }\r\n};\r\n\r\n/**\r\n * Default toolbar button layout with separators\r\n * This is used when toolbar: true but no toolbarButtons provided\r\n */\r\nexport const defaultToolbarButtons = [\r\n toolbarButtons.bold,\r\n toolbarButtons.italic,\r\n toolbarButtons.code,\r\n toolbarButtons.separator,\r\n toolbarButtons.link,\r\n toolbarButtons.separator,\r\n toolbarButtons.h1,\r\n toolbarButtons.h2,\r\n toolbarButtons.h3,\r\n toolbarButtons.separator,\r\n toolbarButtons.bulletList,\r\n toolbarButtons.orderedList,\r\n toolbarButtons.taskList,\r\n toolbarButtons.separator,\r\n toolbarButtons.quote,\r\n toolbarButtons.separator,\r\n toolbarButtons.viewMode\r\n];\r\n", "/**\r\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\r\n * @version 1.0.0\r\n * @license MIT\r\n */\r\n\r\nimport { MarkdownParser } from './parser.js';\r\nimport { ShortcutsManager } from './shortcuts.js';\r\nimport { generateStyles } from './styles.js';\r\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\r\nimport { Toolbar } from './toolbar.js';\r\nimport { LinkTooltip } from './link-tooltip.js';\r\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\r\n\r\n/**\r\n * Build action map from toolbar button configurations\r\n * @param {Array} buttons - Array of button config objects\r\n * @returns {Object} Map of actionId -> action function\r\n */\r\nfunction buildActionsMap(buttons) {\r\n const map = {};\r\n (buttons || []).forEach((btn) => {\r\n if (!btn || btn.name === 'separator') return;\r\n const id = btn.actionId || btn.name;\r\n if (btn.action) {\r\n map[id] = btn.action;\r\n }\r\n });\r\n return map;\r\n}\r\n\r\n/**\r\n * Normalize toolbar buttons for comparison\r\n * @param {Array|null} buttons\r\n * @returns {Array|null}\r\n */\r\nfunction normalizeButtons(buttons) {\r\n const list = buttons || defaultToolbarButtons;\r\n if (!Array.isArray(list)) return null;\r\n return list.map((btn) => ({\r\n name: btn?.name || null,\r\n actionId: btn?.actionId || btn?.name || null,\r\n icon: btn?.icon || null,\r\n title: btn?.title || null\r\n }));\r\n}\r\n\r\n/**\r\n * Determine if toolbar button configuration changed\r\n * @param {Array|null} prevButtons\r\n * @param {Array|null} nextButtons\r\n * @returns {boolean}\r\n */\r\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\r\n const prev = normalizeButtons(prevButtons);\r\n const next = normalizeButtons(nextButtons);\r\n\r\n if (prev === null || next === null) return prev !== next;\r\n if (prev.length !== next.length) return true;\r\n\r\n for (let i = 0; i < prev.length; i++) {\r\n const a = prev[i];\r\n const b = next[i];\r\n if (a.name !== b.name ||\r\n a.actionId !== b.actionId ||\r\n a.icon !== b.icon ||\r\n a.title !== b.title) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * OverType Editor Class\r\n */\r\nclass OverType {\r\n // Static properties\r\n static instances = new WeakMap();\r\n static stylesInjected = false;\r\n static globalListenersInitialized = false;\r\n static instanceCount = 0;\r\n static autoThemeMediaQuery = null; // Media query for auto theme switching\r\n static autoThemeListener = null; // Listener function for auto theme changes\r\n\r\n /**\r\n * Constructor - Always returns an array of instances\r\n * @param {string|Element|NodeList|Array} target - Target element(s)\r\n * @param {Object} options - Configuration options\r\n * @returns {Array} Array of OverType instances\r\n */\r\n constructor(target, options = {}) {\r\n // Convert target to array of elements\r\n let elements;\r\n \r\n if (typeof target === 'string') {\r\n elements = document.querySelectorAll(target);\r\n if (elements.length === 0) {\r\n throw new Error(`No elements found for selector: ${target}`);\r\n }\r\n elements = Array.from(elements);\r\n } else if (target instanceof Element) {\r\n elements = [target];\r\n } else if (target instanceof NodeList) {\r\n elements = Array.from(target);\r\n } else if (Array.isArray(target)) {\r\n elements = target;\r\n } else {\r\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\r\n }\r\n\r\n // Initialize all elements and return array\r\n const instances = elements.map(element => {\r\n // Check for existing instance\r\n if (element.overTypeInstance) {\r\n // Re-init existing instance\r\n element.overTypeInstance.reinit(options);\r\n return element.overTypeInstance;\r\n }\r\n\r\n // Create new instance\r\n const instance = Object.create(OverType.prototype);\r\n instance._init(element, options);\r\n element.overTypeInstance = instance;\r\n OverType.instances.set(element, instance);\r\n return instance;\r\n });\r\n\r\n return instances;\r\n }\r\n\r\n /**\r\n * Internal initialization\r\n * @private\r\n */\r\n _init(element, options = {}) {\r\n this.element = element;\r\n \r\n // Store the original theme option before merging\r\n this.instanceTheme = options.theme || null;\r\n \r\n // Auto theme tracking for instance-level theme\r\n this.autoThemeMediaQuery = null;\r\n this.autoThemeListener = null;\r\n \r\n this.options = this._mergeOptions(options);\r\n this.instanceId = ++OverType.instanceCount;\r\n this.initialized = false;\r\n\r\n // Inject styles if needed\r\n OverType.injectStyles();\r\n\r\n // Initialize global listeners\r\n OverType.initGlobalListeners();\r\n\r\n // Check for existing OverType DOM structure\r\n const container = element.querySelector('.overtype-container');\r\n const wrapper = element.querySelector('.overtype-wrapper');\r\n if (container || wrapper) {\r\n this._recoverFromDOM(container, wrapper);\r\n } else {\r\n this._buildFromScratch();\r\n }\r\n\r\n // Set up instance theme if provided (including auto theme listener)\r\n if (this.instanceTheme) {\r\n this.setTheme(this.instanceTheme);\r\n }\r\n\r\n // Setup shortcuts manager\r\n this.shortcuts = new ShortcutsManager(this);\r\n\r\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\r\n this._rebuildActionsMap();\r\n\r\n // Setup link tooltip\r\n this.linkTooltip = new LinkTooltip(this);\r\n\r\n // Sync scroll positions on initial render\r\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\r\n // Double requestAnimationFrame waits for browser to restore scroll position\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(() => {\r\n this.textarea.scrollTop = this.preview.scrollTop;\r\n this.textarea.scrollLeft = this.preview.scrollLeft;\r\n });\r\n });\r\n\r\n // Mark as initialized\r\n this.initialized = true;\r\n\r\n // Call onChange if provided\r\n if (this.options.onChange) {\r\n this.options.onChange(this.getValue(), this);\r\n }\r\n }\r\n\r\n /**\r\n * Merge user options with defaults\r\n * @private\r\n */\r\n _mergeOptions(options) {\r\n const defaults = {\r\n // Typography\r\n fontSize: '14px',\r\n lineHeight: 1.6,\r\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\r\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\r\n padding: '16px',\r\n \r\n // Mobile styles\r\n mobile: {\r\n fontSize: '16px', // Prevent zoom on iOS\r\n padding: '12px',\r\n lineHeight: 1.5\r\n },\r\n \r\n // Native textarea properties\r\n textareaProps: {},\r\n \r\n // Behavior\r\n autofocus: false,\r\n autoResize: false, // Auto-expand height with content\r\n minHeight: '100px', // Minimum height for autoResize mode\r\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\r\n placeholder: 'Start typing...',\r\n value: '',\r\n \r\n // Callbacks\r\n onChange: null,\r\n onKeydown: null,\r\n \r\n // Features\r\n showActiveLineRaw: false,\r\n showStats: false,\r\n toolbar: false,\r\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\r\n statsFormatter: null,\r\n smartLists: true, // Enable smart list continuation\r\n codeHighlighter: null // Per-instance code highlighter\r\n };\r\n \r\n // Remove theme and colors from options - these are now global\r\n const { theme, colors, ...cleanOptions } = options;\r\n \r\n return {\r\n ...defaults,\r\n ...cleanOptions\r\n };\r\n }\r\n\r\n /**\r\n * Recover from existing DOM structure\r\n * @private\r\n */\r\n _recoverFromDOM(container, wrapper) {\r\n // Handle old structure (wrapper only) or new structure (container + wrapper)\r\n if (container && container.classList.contains('overtype-container')) {\r\n this.container = container;\r\n this.wrapper = container.querySelector('.overtype-wrapper');\r\n } else if (wrapper) {\r\n // Old structure - just wrapper, no container\r\n this.wrapper = wrapper;\r\n // Wrap it in a container for consistency\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-container';\r\n // Use instance theme if provided, otherwise use global theme\r\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\r\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\r\n if (themeName) {\r\n this.container.setAttribute('data-theme', themeName);\r\n }\r\n \r\n // If using instance theme, apply CSS variables to container\r\n if (this.instanceTheme) {\r\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\r\n if (themeObj && themeObj.colors) {\r\n const cssVars = themeToCSSVars(themeObj.colors);\r\n this.container.style.cssText += cssVars;\r\n }\r\n }\r\n wrapper.parentNode.insertBefore(this.container, wrapper);\r\n this.container.appendChild(wrapper);\r\n }\r\n \r\n if (!this.wrapper) {\r\n // No valid structure found\r\n if (container) container.remove();\r\n if (wrapper) wrapper.remove();\r\n this._buildFromScratch();\r\n return;\r\n }\r\n \r\n this.textarea = this.wrapper.querySelector('.overtype-input');\r\n this.preview = this.wrapper.querySelector('.overtype-preview');\r\n\r\n if (!this.textarea || !this.preview) {\r\n // Partial DOM - clear and rebuild\r\n this.container.remove();\r\n this._buildFromScratch();\r\n return;\r\n }\r\n\r\n // Store reference on wrapper\r\n this.wrapper._instance = this;\r\n \r\n // Apply instance-specific styles via CSS custom properties\r\n if (this.options.fontSize) {\r\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\r\n }\r\n if (this.options.lineHeight) {\r\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\r\n }\r\n if (this.options.padding) {\r\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\r\n }\r\n\r\n // Disable autofill, spellcheck, and extensions\r\n this._configureTextarea();\r\n\r\n // Apply any new options\r\n this._applyOptions();\r\n }\r\n\r\n /**\r\n * Build editor from scratch\r\n * @private\r\n */\r\n _buildFromScratch() {\r\n // Extract any existing content\r\n const content = this._extractContent();\r\n\r\n // Clear element\r\n this.element.innerHTML = '';\r\n\r\n // Create DOM structure\r\n this._createDOM();\r\n\r\n // Set initial content\r\n if (content || this.options.value) {\r\n this.setValue(content || this.options.value);\r\n }\r\n\r\n // Apply options\r\n this._applyOptions();\r\n }\r\n\r\n /**\r\n * Extract content from element\r\n * @private\r\n */\r\n _extractContent() {\r\n // Look for existing OverType textarea\r\n const textarea = this.element.querySelector('.overtype-input');\r\n if (textarea) return textarea.value;\r\n\r\n // Use element's text content as fallback\r\n return this.element.textContent || '';\r\n }\r\n\r\n /**\r\n * Create DOM structure\r\n * @private\r\n */\r\n _createDOM() {\r\n // Create container that will hold toolbar and editor\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-container';\r\n \r\n // Set theme on container - use instance theme if provided\r\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\r\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\r\n if (themeName) {\r\n this.container.setAttribute('data-theme', themeName);\r\n }\r\n \r\n // If using instance theme, apply CSS variables to container\r\n if (this.instanceTheme) {\r\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\r\n if (themeObj && themeObj.colors) {\r\n const cssVars = themeToCSSVars(themeObj.colors);\r\n this.container.style.cssText += cssVars;\r\n }\r\n }\r\n \r\n // Create wrapper for editor\r\n this.wrapper = document.createElement('div');\r\n this.wrapper.className = 'overtype-wrapper';\r\n \r\n \r\n // Apply instance-specific styles via CSS custom properties\r\n if (this.options.fontSize) {\r\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\r\n }\r\n if (this.options.lineHeight) {\r\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\r\n }\r\n if (this.options.padding) {\r\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\r\n }\r\n \r\n this.wrapper._instance = this;\r\n\r\n // Create textarea\r\n this.textarea = document.createElement('textarea');\r\n this.textarea.className = 'overtype-input';\r\n this.textarea.placeholder = this.options.placeholder;\r\n this._configureTextarea();\r\n \r\n // Apply any native textarea properties\r\n if (this.options.textareaProps) {\r\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\r\n if (key === 'className' || key === 'class') {\r\n this.textarea.className += ' ' + value;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n Object.assign(this.textarea.style, value);\r\n } else {\r\n this.textarea.setAttribute(key, value);\r\n }\r\n });\r\n }\r\n\r\n // Create preview div\r\n this.preview = document.createElement('div');\r\n this.preview.className = 'overtype-preview';\r\n this.preview.setAttribute('aria-hidden', 'true');\r\n\r\n // Assemble DOM\r\n this.wrapper.appendChild(this.textarea);\r\n this.wrapper.appendChild(this.preview);\r\n \r\n // No need to prevent link clicks - pointer-events handles this\r\n \r\n // Add wrapper to container first\r\n this.container.appendChild(this.wrapper);\r\n \r\n // Add stats bar at the end (bottom) if enabled\r\n if (this.options.showStats) {\r\n this.statsBar = document.createElement('div');\r\n this.statsBar.className = 'overtype-stats';\r\n this.container.appendChild(this.statsBar);\r\n this._updateStats();\r\n }\r\n \r\n // Add container to element\r\n this.element.appendChild(this.container);\r\n \r\n // Setup auto-resize if enabled\r\n if (this.options.autoResize) {\r\n this._setupAutoResize();\r\n } else {\r\n // Ensure auto-resize class is removed if not using auto-resize\r\n this.container.classList.remove('overtype-auto-resize');\r\n }\r\n }\r\n\r\n /**\r\n * Configure textarea attributes\r\n * @private\r\n */\r\n _configureTextarea() {\r\n this.textarea.setAttribute('autocomplete', 'off');\r\n this.textarea.setAttribute('autocorrect', 'off');\r\n this.textarea.setAttribute('autocapitalize', 'off');\r\n this.textarea.setAttribute('spellcheck', 'false');\r\n this.textarea.setAttribute('data-gramm', 'false');\r\n this.textarea.setAttribute('data-gramm_editor', 'false');\r\n this.textarea.setAttribute('data-enable-grammarly', 'false');\r\n }\r\n\r\n /**\r\n * Create and setup toolbar\r\n * @private\r\n */\r\n _createToolbar() {\r\n // Use provided toolbarButtons or default to defaultToolbarButtons\r\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\r\n\r\n this.toolbar = new Toolbar(this, { toolbarButtons });\r\n this.toolbar.create();\r\n\r\n // Store listener references for cleanup\r\n this._toolbarSelectionListener = () => {\r\n if (this.toolbar) {\r\n this.toolbar.updateButtonStates();\r\n }\r\n };\r\n this._toolbarInputListener = () => {\r\n if (this.toolbar) {\r\n this.toolbar.updateButtonStates();\r\n }\r\n };\r\n\r\n // Add listeners\r\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\r\n this.textarea.addEventListener('input', this._toolbarInputListener);\r\n }\r\n\r\n /**\r\n * Cleanup toolbar event listeners\r\n * @private\r\n */\r\n _cleanupToolbarListeners() {\r\n if (this._toolbarSelectionListener) {\r\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\r\n this._toolbarSelectionListener = null;\r\n }\r\n if (this._toolbarInputListener) {\r\n this.textarea.removeEventListener('input', this._toolbarInputListener);\r\n this._toolbarInputListener = null;\r\n }\r\n }\r\n\r\n /**\r\n * Rebuild the action map from current toolbar button configuration\r\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\r\n * @private\r\n */\r\n _rebuildActionsMap() {\r\n // Always start with default actions (shortcuts always work regardless of toolbar config)\r\n this.actionsById = buildActionsMap(defaultToolbarButtons);\r\n\r\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\r\n if (this.options.toolbarButtons) {\r\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\r\n }\r\n }\r\n\r\n /**\r\n * Apply options to the editor\r\n * @private\r\n */\r\n _applyOptions() {\r\n // Apply autofocus\r\n if (this.options.autofocus) {\r\n this.textarea.focus();\r\n }\r\n\r\n // Setup or remove auto-resize\r\n if (this.options.autoResize) {\r\n if (!this.container.classList.contains('overtype-auto-resize')) {\r\n this._setupAutoResize();\r\n }\r\n } else {\r\n // Ensure auto-resize class is removed\r\n this.container.classList.remove('overtype-auto-resize');\r\n }\r\n\r\n // Handle toolbar option changes\r\n if (this.options.toolbar && !this.toolbar) {\r\n // Create toolbar if enabled and doesn't exist\r\n this._createToolbar();\r\n } else if (!this.options.toolbar && this.toolbar) {\r\n // Destroy toolbar if disabled and exists\r\n this._cleanupToolbarListeners();\r\n this.toolbar.destroy();\r\n this.toolbar = null;\r\n }\r\n\r\n // Update preview with initial content\r\n this.updatePreview();\r\n }\r\n\r\n /**\r\n * Update preview with parsed markdown\r\n */\r\n updatePreview() {\r\n const text = this.textarea.value;\r\n const cursorPos = this.textarea.selectionStart;\r\n const activeLine = this._getCurrentLine(text, cursorPos);\r\n\r\n // Detect if we're in preview mode\r\n const isPreviewMode = this.container.dataset.mode === 'preview';\r\n\r\n // Parse markdown\r\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\r\n this.preview.innerHTML = html || 'Start typing...';\r\n \r\n // Apply code block backgrounds\r\n this._applyCodeBlockBackgrounds();\r\n \r\n // Links always have real hrefs now - no need to update them\r\n \r\n // Update stats if enabled\r\n if (this.options.showStats && this.statsBar) {\r\n this._updateStats();\r\n }\r\n \r\n // Trigger onChange callback\r\n if (this.options.onChange && this.initialized) {\r\n this.options.onChange(text, this);\r\n }\r\n }\r\n\r\n /**\r\n * Apply background styling to code blocks\r\n * @private\r\n */\r\n _applyCodeBlockBackgrounds() {\r\n // Find all code fence elements\r\n const codeFences = this.preview.querySelectorAll('.code-fence');\r\n \r\n // Process pairs of code fences\r\n for (let i = 0; i < codeFences.length - 1; i += 2) {\r\n const openFence = codeFences[i];\r\n const closeFence = codeFences[i + 1];\r\n \r\n // Get parent divs\r\n const openParent = openFence.parentElement;\r\n const closeParent = closeFence.parentElement;\r\n \r\n if (!openParent || !closeParent) continue;\r\n \r\n // Make fences display: block\r\n openFence.style.display = 'block';\r\n closeFence.style.display = 'block';\r\n \r\n // Apply class to parent divs\r\n openParent.classList.add('code-block-line');\r\n closeParent.classList.add('code-block-line');\r\n \r\n // With the new structure, there's a
     block between fences, not DIVs\r\n        // We don't need to process anything between the fences anymore\r\n        // The 
     structure already handles the content correctly\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Get current line number from cursor position\r\n     * @private\r\n     */\r\n    _getCurrentLine(text, cursorPos) {\r\n      const lines = text.substring(0, cursorPos).split('\\n');\r\n      return lines.length - 1;\r\n    }\r\n\r\n    /**\r\n     * Handle input events\r\n     * @private\r\n     */\r\n    handleInput(event) {\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Handle keydown events\r\n     * @private\r\n     */\r\n    handleKeydown(event) {\r\n      // Handle Tab key to prevent focus loss and insert spaces\r\n      if (event.key === 'Tab') {\r\n        const start = this.textarea.selectionStart;\r\n        const end = this.textarea.selectionEnd;\r\n        const value = this.textarea.value;\r\n\r\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\r\n        if (event.shiftKey && start === end) {\r\n          return;\r\n        }\r\n\r\n        event.preventDefault();\r\n\r\n        // If there's a selection, indent/outdent based on shift key\r\n        if (start !== end && event.shiftKey) {\r\n          // Outdent: remove 2 spaces from start of each selected line\r\n          const before = value.substring(0, start);\r\n          const selection = value.substring(start, end);\r\n          const after = value.substring(end);\r\n          \r\n          const lines = selection.split('\\n');\r\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\r\n          \r\n          // Try to use execCommand first to preserve undo history\r\n          if (document.execCommand) {\r\n            // Select the text that needs to be replaced\r\n            this.textarea.setSelectionRange(start, end);\r\n            document.execCommand('insertText', false, outdented);\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = before + outdented + after;\r\n            this.textarea.selectionStart = start;\r\n            this.textarea.selectionEnd = start + outdented.length;\r\n          }\r\n        } else if (start !== end) {\r\n          // Indent: add 2 spaces to start of each selected line\r\n          const before = value.substring(0, start);\r\n          const selection = value.substring(start, end);\r\n          const after = value.substring(end);\r\n          \r\n          const lines = selection.split('\\n');\r\n          const indented = lines.map(line => '  ' + line).join('\\n');\r\n          \r\n          // Try to use execCommand first to preserve undo history\r\n          if (document.execCommand) {\r\n            // Select the text that needs to be replaced\r\n            this.textarea.setSelectionRange(start, end);\r\n            document.execCommand('insertText', false, indented);\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = before + indented + after;\r\n            this.textarea.selectionStart = start;\r\n            this.textarea.selectionEnd = start + indented.length;\r\n          }\r\n        } else {\r\n          // No selection: just insert 2 spaces\r\n          // Use execCommand to preserve undo history\r\n          if (document.execCommand) {\r\n            document.execCommand('insertText', false, '  ');\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\r\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\r\n          }\r\n        }\r\n        \r\n        // Trigger input event to update preview\r\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n        return;\r\n      }\r\n      \r\n      // Handle Enter key for smart list continuation\r\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\r\n        if (this.handleSmartListContinuation()) {\r\n          event.preventDefault();\r\n          return;\r\n        }\r\n      }\r\n      \r\n      // Let shortcuts manager handle other keys\r\n      const handled = this.shortcuts.handleKeydown(event);\r\n      \r\n      // Call user callback if provided\r\n      if (!handled && this.options.onKeydown) {\r\n        this.options.onKeydown(event, this);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Handle smart list continuation\r\n     * @returns {boolean} Whether the event was handled\r\n     */\r\n    handleSmartListContinuation() {\r\n      const textarea = this.textarea;\r\n      const cursorPos = textarea.selectionStart;\r\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\r\n      \r\n      if (!context || !context.inList) return false;\r\n      \r\n      // Handle empty list item (exit list)\r\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\r\n        this.deleteListMarker(context);\r\n        return true;\r\n      }\r\n      \r\n      // Handle text splitting if cursor is in middle of content\r\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\r\n        this.splitListItem(context, cursorPos);\r\n      } else {\r\n        // Just add new item after current line\r\n        this.insertNewListItem(context);\r\n      }\r\n      \r\n      // Handle numbered list renumbering\r\n      if (context.listType === 'numbered') {\r\n        this.scheduleNumberedListUpdate();\r\n      }\r\n      \r\n      return true;\r\n    }\r\n    \r\n    /**\r\n     * Delete list marker and exit list\r\n     * @private\r\n     */\r\n    deleteListMarker(context) {\r\n      // Select from line start to marker end\r\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\r\n      document.execCommand('delete');\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Insert new list item\r\n     * @private\r\n     */\r\n    insertNewListItem(context) {\r\n      const newItem = MarkdownParser.createNewListItem(context);\r\n      document.execCommand('insertText', false, '\\n' + newItem);\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Split list item at cursor position\r\n     * @private\r\n     */\r\n    splitListItem(context, cursorPos) {\r\n      // Get text after cursor\r\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\r\n      \r\n      // Delete text after cursor\r\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\r\n      document.execCommand('delete');\r\n      \r\n      // Insert new list item with remaining text\r\n      const newItem = MarkdownParser.createNewListItem(context);\r\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\r\n      \r\n      // Position cursor after new list marker\r\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\r\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Schedule numbered list renumbering\r\n     * @private\r\n     */\r\n    scheduleNumberedListUpdate() {\r\n      // Clear any pending update\r\n      if (this.numberUpdateTimeout) {\r\n        clearTimeout(this.numberUpdateTimeout);\r\n      }\r\n      \r\n      // Schedule update after current input cycle\r\n      this.numberUpdateTimeout = setTimeout(() => {\r\n        this.updateNumberedLists();\r\n      }, 10);\r\n    }\r\n    \r\n    /**\r\n     * Update/renumber all numbered lists\r\n     * @private\r\n     */\r\n    updateNumberedLists() {\r\n      const value = this.textarea.value;\r\n      const cursorPos = this.textarea.selectionStart;\r\n      \r\n      const newValue = MarkdownParser.renumberLists(value);\r\n      \r\n      if (newValue !== value) {\r\n        // Calculate cursor offset\r\n        let offset = 0;\r\n        const oldLines = value.split('\\n');\r\n        const newLines = newValue.split('\\n');\r\n        let charCount = 0;\r\n        \r\n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\r\n          if (oldLines[i] !== newLines[i]) {\r\n            const diff = newLines[i].length - oldLines[i].length;\r\n            if (charCount + oldLines[i].length < cursorPos) {\r\n              offset += diff;\r\n            }\r\n          }\r\n          charCount += oldLines[i].length + 1; // +1 for newline\r\n        }\r\n        \r\n        // Update textarea\r\n        this.textarea.value = newValue;\r\n        const newCursorPos = cursorPos + offset;\r\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\r\n        \r\n        // Trigger update\r\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Handle scroll events\r\n     * @private\r\n     */\r\n    handleScroll(event) {\r\n      // Sync preview scroll with textarea\r\n      this.preview.scrollTop = this.textarea.scrollTop;\r\n      this.preview.scrollLeft = this.textarea.scrollLeft;\r\n    }\r\n\r\n    /**\r\n     * Get editor content\r\n     * @returns {string} Current markdown content\r\n     */\r\n    getValue() {\r\n      return this.textarea.value;\r\n    }\r\n\r\n    /**\r\n     * Set editor content\r\n     * @param {string} value - Markdown content to set\r\n     */\r\n    setValue(value) {\r\n      this.textarea.value = value;\r\n      this.updatePreview();\r\n\r\n      // Update height if auto-resize is enabled\r\n      if (this.options.autoResize) {\r\n        this._updateAutoHeight();\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Execute an action by ID\r\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\r\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\r\n     * @param {Event|null} event - Optional event that triggered the action\r\n     * @returns {Promise} Whether the action was executed successfully\r\n     */\r\n    async performAction(actionId, event = null) {\r\n      const textarea = this.textarea;\r\n      if (!textarea) return false;\r\n\r\n      const action = this.actionsById?.[actionId];\r\n      if (!action) {\r\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\r\n        return false;\r\n      }\r\n\r\n      textarea.focus();\r\n\r\n      try {\r\n        await action({\r\n          editor: this,\r\n          getValue: () => this.getValue(),\r\n          setValue: (value) => this.setValue(value),\r\n          event\r\n        });\r\n        // Note: actions are responsible for dispatching input event\r\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\r\n        return true;\r\n      } catch (error) {\r\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\r\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\r\n          detail: { actionId, error }\r\n        }));\r\n        return false;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Get the rendered HTML of the current content\r\n     * @param {Object} options - Rendering options\r\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\r\n     * @returns {string} Rendered HTML\r\n     */\r\n    getRenderedHTML(options = {}) {\r\n      const markdown = this.getValue();\r\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\r\n\r\n      if (options.cleanHTML) {\r\n        // Remove all syntax marker spans for clean HTML export\r\n        html = html.replace(/.*?<\\/span>/g, '');\r\n        // Remove OverType-specific classes\r\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\r\n        // Clean up empty class attributes\r\n        html = html.replace(/\\sclass=\"\"/g, '');\r\n      }\r\n      \r\n      return html;\r\n    }\r\n\r\n    /**\r\n     * Get the current preview element's HTML\r\n     * This includes all syntax markers and OverType styling\r\n     * @returns {string} Current preview HTML (as displayed)\r\n     */\r\n    getPreviewHTML() {\r\n      return this.preview.innerHTML;\r\n    }\r\n    \r\n    /**\r\n     * Get clean HTML without any OverType-specific markup\r\n     * Useful for exporting to other formats or storage\r\n     * @returns {string} Clean HTML suitable for export\r\n     */\r\n    getCleanHTML() {\r\n      return this.getRenderedHTML({ cleanHTML: true });\r\n    }\r\n\r\n    /**\r\n     * Focus the editor\r\n     */\r\n    focus() {\r\n      this.textarea.focus();\r\n    }\r\n\r\n    /**\r\n     * Blur the editor\r\n     */\r\n    blur() {\r\n      this.textarea.blur();\r\n    }\r\n\r\n    /**\r\n     * Check if editor is initialized\r\n     * @returns {boolean}\r\n     */\r\n    isInitialized() {\r\n      return this.initialized;\r\n    }\r\n\r\n    /**\r\n     * Re-initialize with new options\r\n     * @param {Object} options - New options to apply\r\n     */\r\n    reinit(options = {}) {\r\n      const prevToolbarButtons = this.options?.toolbarButtons;\r\n      this.options = this._mergeOptions({ ...this.options, ...options });\r\n      const toolbarNeedsRebuild = this.toolbar &&\r\n        this.options.toolbar &&\r\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\r\n\r\n      // Rebuild action map in case toolbarButtons changed\r\n      this._rebuildActionsMap();\r\n\r\n      if (toolbarNeedsRebuild) {\r\n        this._cleanupToolbarListeners();\r\n        this.toolbar.destroy();\r\n        this.toolbar = null;\r\n        this._createToolbar();\r\n      }\r\n\r\n      this._applyOptions();\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Set theme for this instance\r\n     * @param {string|Object} theme - Theme name or custom theme object\r\n     * @returns {this} Returns this for chaining\r\n     */\r\n    setTheme(theme) {\r\n      // Clean up existing auto theme listener if any\r\n      this._cleanupAutoThemeListener();\r\n\r\n      // Update instance theme\r\n      this.instanceTheme = theme;\r\n\r\n      // Handle auto theme\r\n      if (theme === 'auto') {\r\n        this._setupAutoThemeListener();\r\n        // Apply the initial resolved theme\r\n        const resolvedTheme = resolveAutoTheme('auto');\r\n        this._applyResolvedTheme(resolvedTheme);\r\n      } else {\r\n        // Get theme object for non-auto themes\r\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\r\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n\r\n        // Update container theme attribute\r\n        if (themeName) {\r\n          this.container.setAttribute('data-theme', themeName);\r\n        }\r\n\r\n        // Apply CSS variables to container for instance override\r\n        if (themeObj && themeObj.colors) {\r\n          const cssVars = themeToCSSVars(themeObj.colors);\r\n          this.container.style.cssText += cssVars;\r\n        }\r\n\r\n        // Update preview to reflect new theme\r\n        this.updatePreview();\r\n      }\r\n\r\n      return this;\r\n    }\r\n\r\n    /**\r\n     * Apply a resolved theme name (used by auto theme)\r\n     * @private\r\n     * @param {string} themeName - Resolved theme name\r\n     */\r\n    _applyResolvedTheme(themeName) {\r\n      const themeObj = getTheme(themeName);\r\n      \r\n      // Update container with resolved theme, but keep auto in data-theme for tracking\r\n      this.container.setAttribute('data-theme', 'auto');\r\n      this.container.setAttribute('data-resolved-theme', themeName);\r\n\r\n      // Apply CSS variables\r\n      if (themeObj && themeObj.colors) {\r\n        const cssVars = themeToCSSVars(themeObj.colors);\r\n        this.container.style.cssText += cssVars;\r\n      }\r\n\r\n      // Update preview to reflect new theme\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Setup auto theme listener for instance\r\n     * @private\r\n     */\r\n    _setupAutoThemeListener() {\r\n      if (!window.matchMedia) return;\r\n\r\n      this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n      this.autoThemeListener = (event) => {\r\n        const resolvedTheme = event.matches ? 'cave' : 'solar';\r\n        this._applyResolvedTheme(resolvedTheme);\r\n      };\r\n\r\n      // Use addEventListener if available (modern browsers)\r\n      if (this.autoThemeMediaQuery.addEventListener) {\r\n        this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener);\r\n      } else if (this.autoThemeMediaQuery.addListener) {\r\n        // Fallback for older browsers\r\n        this.autoThemeMediaQuery.addListener(this.autoThemeListener);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Clean up auto theme listener for instance\r\n     * @private\r\n     */\r\n    _cleanupAutoThemeListener() {\r\n      if (this.autoThemeMediaQuery && this.autoThemeListener) {\r\n        if (this.autoThemeMediaQuery.removeEventListener) {\r\n          this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener);\r\n        } else if (this.autoThemeMediaQuery.removeListener) {\r\n          // Fallback for older browsers\r\n          this.autoThemeMediaQuery.removeListener(this.autoThemeListener);\r\n        }\r\n        this.autoThemeMediaQuery = null;\r\n        this.autoThemeListener = null;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Set instance-specific code highlighter\r\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n     */\r\n    setCodeHighlighter(highlighter) {\r\n      this.options.codeHighlighter = highlighter;\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Update stats bar\r\n     * @private\r\n     */\r\n    _updateStats() {\r\n      if (!this.statsBar) return;\r\n      \r\n      const value = this.textarea.value;\r\n      const lines = value.split('\\n');\r\n      const chars = value.length;\r\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\r\n      \r\n      // Calculate line and column\r\n      const selectionStart = this.textarea.selectionStart;\r\n      const beforeCursor = value.substring(0, selectionStart);\r\n      const linesBeforeCursor = beforeCursor.split('\\n');\r\n      const currentLine = linesBeforeCursor.length;\r\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\r\n      \r\n      // Use custom formatter if provided\r\n      if (this.options.statsFormatter) {\r\n        this.statsBar.innerHTML = this.options.statsFormatter({\r\n          chars,\r\n          words,\r\n          lines: lines.length,\r\n          line: currentLine,\r\n          column: currentColumn\r\n        });\r\n      } else {\r\n        // Default format with live dot\r\n        this.statsBar.innerHTML = `\r\n          
    \r\n \r\n ${chars} chars, ${words} words, ${lines.length} lines\r\n
    \r\n
    Line ${currentLine}, Col ${currentColumn}
    \r\n `;\r\n }\r\n }\r\n \r\n /**\r\n * Setup auto-resize functionality\r\n * @private\r\n */\r\n _setupAutoResize() {\r\n // Add auto-resize class for styling\r\n this.container.classList.add('overtype-auto-resize');\r\n \r\n // Store previous height for comparison\r\n this.previousHeight = null;\r\n \r\n // Initial height update\r\n this._updateAutoHeight();\r\n \r\n // Listen for input events\r\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\r\n \r\n // Listen for window resize\r\n window.addEventListener('resize', () => this._updateAutoHeight());\r\n }\r\n \r\n /**\r\n * Update height based on scrollHeight\r\n * @private\r\n */\r\n _updateAutoHeight() {\r\n if (!this.options.autoResize) return;\r\n \r\n const textarea = this.textarea;\r\n const preview = this.preview;\r\n const wrapper = this.wrapper;\r\n \r\n // Get computed styles\r\n const computed = window.getComputedStyle(textarea);\r\n const paddingTop = parseFloat(computed.paddingTop);\r\n const paddingBottom = parseFloat(computed.paddingBottom);\r\n \r\n // Store scroll positions\r\n const scrollTop = textarea.scrollTop;\r\n \r\n // Reset height to get accurate scrollHeight\r\n textarea.style.setProperty('height', 'auto', 'important');\r\n \r\n // Calculate new height based on scrollHeight\r\n let newHeight = textarea.scrollHeight;\r\n \r\n // Apply min height constraint\r\n if (this.options.minHeight) {\r\n const minHeight = parseInt(this.options.minHeight);\r\n newHeight = Math.max(newHeight, minHeight);\r\n }\r\n \r\n // Apply max height constraint\r\n let overflow = 'hidden';\r\n if (this.options.maxHeight) {\r\n const maxHeight = parseInt(this.options.maxHeight);\r\n if (newHeight > maxHeight) {\r\n newHeight = maxHeight;\r\n overflow = 'auto';\r\n }\r\n }\r\n \r\n // Apply the new height to all elements with !important to override base styles\r\n const heightPx = newHeight + 'px';\r\n textarea.style.setProperty('height', heightPx, 'important');\r\n textarea.style.setProperty('overflow-y', overflow, 'important');\r\n \r\n preview.style.setProperty('height', heightPx, 'important');\r\n preview.style.setProperty('overflow-y', overflow, 'important');\r\n \r\n wrapper.style.setProperty('height', heightPx, 'important');\r\n \r\n // Restore scroll position\r\n textarea.scrollTop = scrollTop;\r\n preview.scrollTop = scrollTop;\r\n \r\n // Track if height changed\r\n if (this.previousHeight !== newHeight) {\r\n this.previousHeight = newHeight;\r\n // Could dispatch a custom event here if needed\r\n }\r\n }\r\n \r\n /**\r\n * Show or hide stats bar\r\n * @param {boolean} show - Whether to show stats\r\n */\r\n showStats(show) {\r\n this.options.showStats = show;\r\n\r\n if (show && !this.statsBar) {\r\n // Create stats bar (add to container, not wrapper)\r\n this.statsBar = document.createElement('div');\r\n this.statsBar.className = 'overtype-stats';\r\n this.container.appendChild(this.statsBar);\r\n this._updateStats();\r\n } else if (show && this.statsBar) {\r\n // Already visible - refresh stats (useful after changing statsFormatter)\r\n this._updateStats();\r\n } else if (!show && this.statsBar) {\r\n // Remove stats bar\r\n this.statsBar.remove();\r\n this.statsBar = null;\r\n }\r\n }\r\n \r\n /**\r\n * Show normal edit mode (overlay with markdown preview)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showNormalEditMode() {\r\n this.container.dataset.mode = 'normal';\r\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\r\n\r\n // Always sync scroll from preview to textarea\r\n requestAnimationFrame(() => {\r\n this.textarea.scrollTop = this.preview.scrollTop;\r\n this.textarea.scrollLeft = this.preview.scrollLeft;\r\n });\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Show plain textarea mode (no overlay)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showPlainTextarea() {\r\n this.container.dataset.mode = 'plain';\r\n\r\n // Update toolbar button if exists\r\n if (this.toolbar) {\r\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\r\n if (toggleBtn) {\r\n toggleBtn.classList.remove('active');\r\n toggleBtn.title = 'Show markdown preview';\r\n }\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Show preview mode (read-only view)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showPreviewMode() {\r\n this.container.dataset.mode = 'preview';\r\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\r\n return this;\r\n }\r\n\r\n /**\r\n * Destroy the editor instance\r\n */\r\n destroy() {\r\n // Clean up auto theme listener\r\n this._cleanupAutoThemeListener();\r\n\r\n // Remove instance reference\r\n this.element.overTypeInstance = null;\r\n OverType.instances.delete(this.element);\r\n\r\n // Cleanup shortcuts\r\n if (this.shortcuts) {\r\n this.shortcuts.destroy();\r\n }\r\n\r\n // Remove DOM if created by us\r\n if (this.wrapper) {\r\n const content = this.getValue();\r\n this.wrapper.remove();\r\n \r\n // Restore original content\r\n this.element.textContent = content;\r\n }\r\n\r\n this.initialized = false;\r\n }\r\n\r\n // ===== Static Methods =====\r\n\r\n /**\r\n * Initialize multiple editors (static convenience method)\r\n * @param {string|Element|NodeList|Array} target - Target element(s)\r\n * @param {Object} options - Configuration options\r\n * @returns {Array} Array of OverType instances\r\n */\r\n static init(target, options = {}) {\r\n return new OverType(target, options);\r\n }\r\n\r\n /**\r\n * Initialize editors with options from data-ot-* attributes\r\n * @param {string} selector - CSS selector for target elements\r\n * @param {Object} defaults - Default options (data attrs override these)\r\n * @returns {Array} Array of OverType instances\r\n * @example\r\n * // HTML:
    \r\n * OverType.initFromData('.editor', { fontSize: '14px' });\r\n */\r\n static initFromData(selector, defaults = {}) {\r\n const elements = document.querySelectorAll(selector);\r\n return Array.from(elements).map(el => {\r\n const options = { ...defaults };\r\n\r\n // Parse data-ot-* attributes (kebab-case to camelCase)\r\n for (const attr of el.attributes) {\r\n if (attr.name.startsWith('data-ot-')) {\r\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\r\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\r\n options[key] = OverType._parseDataValue(attr.value);\r\n }\r\n }\r\n\r\n return new OverType(el, options);\r\n });\r\n }\r\n\r\n /**\r\n * Parse a data attribute value to the appropriate type\r\n * @private\r\n */\r\n static _parseDataValue(value) {\r\n if (value === 'true') return true;\r\n if (value === 'false') return false;\r\n if (value === 'null') return null;\r\n if (value !== '' && !isNaN(Number(value))) return Number(value);\r\n return value;\r\n }\r\n\r\n /**\r\n * Get instance from element\r\n * @param {Element} element - DOM element\r\n * @returns {OverType|null} OverType instance or null\r\n */\r\n static getInstance(element) {\r\n return element.overTypeInstance || OverType.instances.get(element) || null;\r\n }\r\n\r\n /**\r\n * Destroy all instances\r\n */\r\n static destroyAll() {\r\n const elements = document.querySelectorAll('[data-overtype-instance]');\r\n elements.forEach(element => {\r\n const instance = OverType.getInstance(element);\r\n if (instance) {\r\n instance.destroy();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Inject styles into the document\r\n * @param {boolean} force - Force re-injection\r\n */\r\n static injectStyles(force = false) {\r\n if (OverType.stylesInjected && !force) return;\r\n\r\n // Remove any existing OverType styles\r\n const existing = document.querySelector('style.overtype-styles');\r\n if (existing) {\r\n existing.remove();\r\n }\r\n\r\n // Generate and inject new styles with current theme\r\n const theme = OverType.currentTheme || solar;\r\n const styles = generateStyles({ theme });\r\n const styleEl = document.createElement('style');\r\n styleEl.className = 'overtype-styles';\r\n styleEl.textContent = styles;\r\n document.head.appendChild(styleEl);\r\n\r\n OverType.stylesInjected = true;\r\n }\r\n \r\n /**\r\n * Set global theme for all OverType instances\r\n * @param {string|Object} theme - Theme name or custom theme object\r\n * @param {Object} customColors - Optional color overrides\r\n */\r\n static setTheme(theme, customColors = null) {\r\n // Clean up existing auto theme listener\r\n OverType._cleanupGlobalAutoThemeListener();\r\n\r\n // Handle auto theme at global level\r\n if (theme === 'auto') {\r\n OverType._setupGlobalAutoThemeListener();\r\n // Apply the initial resolved theme\r\n const resolvedTheme = resolveAutoTheme('auto');\r\n OverType._applyGlobalResolvedTheme(resolvedTheme, customColors);\r\n } else {\r\n // Process theme\r\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\r\n\r\n // Apply custom colors if provided\r\n if (customColors) {\r\n themeObj = mergeTheme(themeObj, customColors);\r\n }\r\n\r\n // Store as current theme\r\n OverType.currentTheme = themeObj;\r\n\r\n // Re-inject styles with new theme\r\n OverType.injectStyles(true);\r\n\r\n // Update all existing instances - update container theme attribute\r\n document.querySelectorAll('.overtype-container').forEach(container => {\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n if (themeName) {\r\n container.setAttribute('data-theme', themeName);\r\n }\r\n });\r\n\r\n // Also handle any old-style wrappers without containers\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n if (!wrapper.closest('.overtype-container')) {\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n if (themeName) {\r\n wrapper.setAttribute('data-theme', themeName);\r\n }\r\n }\r\n\r\n // Trigger preview update for the instance\r\n const instance = wrapper._instance;\r\n if (instance) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components (shadow DOM instances)\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n // Set the theme attribute to update the theme name\r\n if (themeName && typeof webComponent.setAttribute === 'function') {\r\n webComponent.setAttribute('theme', themeName);\r\n }\r\n // Also call refreshTheme() to handle cases where the theme name stays the same\r\n // but the theme object's properties have changed\r\n if (typeof webComponent.refreshTheme === 'function') {\r\n webComponent.refreshTheme();\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Apply a resolved theme globally (used by auto theme)\r\n * @private\r\n * @param {string} themeName - Resolved theme name\r\n * @param {Object} customColors - Optional color overrides\r\n */\r\n static _applyGlobalResolvedTheme(themeName, customColors = null) {\r\n let themeObj = getTheme(themeName);\r\n\r\n // Apply custom colors if provided\r\n if (customColors) {\r\n themeObj = mergeTheme(themeObj, customColors);\r\n }\r\n\r\n // Store as current theme\r\n OverType.currentTheme = themeObj;\r\n\r\n // Re-inject styles with new theme\r\n OverType.injectStyles(true);\r\n\r\n // Update all containers with resolved theme, but keep 'auto' for tracking\r\n document.querySelectorAll('.overtype-container').forEach(container => {\r\n container.setAttribute('data-theme', 'auto');\r\n container.setAttribute('data-resolved-theme', themeName);\r\n });\r\n\r\n // Also handle any old-style wrappers without containers\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n if (!wrapper.closest('.overtype-container')) {\r\n wrapper.setAttribute('data-theme', 'auto');\r\n wrapper.setAttribute('data-resolved-theme', themeName);\r\n }\r\n\r\n // Trigger preview update for the instance\r\n const instance = wrapper._instance;\r\n if (instance) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.setAttribute === 'function') {\r\n webComponent.setAttribute('theme', 'auto');\r\n webComponent.setAttribute('data-resolved-theme', themeName);\r\n }\r\n if (typeof webComponent.refreshTheme === 'function') {\r\n webComponent.refreshTheme();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Setup global auto theme listener\r\n * @private\r\n */\r\n static _setupGlobalAutoThemeListener() {\r\n if (!window.matchMedia) return;\r\n\r\n OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n OverType.autoThemeListener = (event) => {\r\n const resolvedTheme = event.matches ? 'cave' : 'solar';\r\n OverType._applyGlobalResolvedTheme(resolvedTheme);\r\n };\r\n\r\n // Use addEventListener if available (modern browsers)\r\n if (OverType.autoThemeMediaQuery.addEventListener) {\r\n OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener);\r\n } else if (OverType.autoThemeMediaQuery.addListener) {\r\n // Fallback for older browsers\r\n OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener);\r\n }\r\n }\r\n\r\n /**\r\n * Clean up global auto theme listener\r\n * @private\r\n */\r\n static _cleanupGlobalAutoThemeListener() {\r\n if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) {\r\n if (OverType.autoThemeMediaQuery.removeEventListener) {\r\n OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener);\r\n } else if (OverType.autoThemeMediaQuery.removeListener) {\r\n // Fallback for older browsers\r\n OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener);\r\n }\r\n OverType.autoThemeMediaQuery = null;\r\n OverType.autoThemeListener = null;\r\n }\r\n }\r\n\r\n /**\r\n * Set global code highlighter for all OverType instances\r\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n */\r\n static setCodeHighlighter(highlighter) {\r\n MarkdownParser.setCodeHighlighter(highlighter);\r\n\r\n // Update all existing instances in light DOM\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n const instance = wrapper._instance;\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components (shadow DOM instances)\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.getEditor === 'function') {\r\n const instance = webComponent.getEditor();\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Set custom syntax processor for extending markdown parsing\r\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\r\n * @example\r\n * OverType.setCustomSyntax((html) => {\r\n * // Highlight footnote references [^1]\r\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\r\n * });\r\n */\r\n static setCustomSyntax(processor) {\r\n MarkdownParser.setCustomSyntax(processor);\r\n\r\n // Update all existing instances\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n const instance = wrapper._instance;\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.getEditor === 'function') {\r\n const instance = webComponent.getEditor();\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Initialize global event listeners\r\n */\r\n static initGlobalListeners() {\r\n if (OverType.globalListenersInitialized) return;\r\n\r\n // Input event\r\n document.addEventListener('input', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleInput(e);\r\n }\r\n });\r\n\r\n // Keydown event\r\n document.addEventListener('keydown', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleKeydown(e);\r\n }\r\n });\r\n\r\n // Scroll event\r\n document.addEventListener('scroll', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleScroll(e);\r\n }\r\n }, true);\r\n\r\n // Selection change event\r\n document.addEventListener('selectionchange', (e) => {\r\n const activeElement = document.activeElement;\r\n if (activeElement && activeElement.classList.contains('overtype-input')) {\r\n const wrapper = activeElement.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) {\r\n // Update stats bar for cursor position\r\n if (instance.options.showStats && instance.statsBar) {\r\n instance._updateStats();\r\n }\r\n // Debounce updates\r\n clearTimeout(instance._selectionTimeout);\r\n instance._selectionTimeout = setTimeout(() => {\r\n instance.updatePreview();\r\n }, 50);\r\n }\r\n }\r\n });\r\n\r\n OverType.globalListenersInitialized = true;\r\n }\r\n}\r\n\r\n// Export classes for advanced usage\r\nOverType.MarkdownParser = MarkdownParser;\r\nOverType.ShortcutsManager = ShortcutsManager;\r\n\r\n// Export theme utilities\r\nOverType.themes = { solar, cave: getTheme('cave') };\r\nOverType.getTheme = getTheme;\r\n\r\n// Set default theme\r\nOverType.currentTheme = solar;\r\n\r\n// Export for module systems\r\nexport default OverType;\r\nexport { OverType };\r\n\r\n// Export toolbar buttons for custom toolbar configurations\r\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\r\n"], + "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') {\n return themeName;\n }\n\n // Check for system dark mode preference\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static autoThemeMediaQuery = null; // Media query for auto theme switching\n static autoThemeListener = null; // Listener function for auto theme changes\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Clean up existing auto theme listener if any\n      this._cleanupAutoThemeListener();\n\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Handle auto theme\n      if (theme === 'auto') {\n        this._setupAutoThemeListener();\n        // Apply the initial resolved theme\n        const resolvedTheme = resolveAutoTheme('auto');\n        this._applyResolvedTheme(resolvedTheme);\n      } else {\n        // Get theme object for non-auto themes\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n        // Update container theme attribute\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        // Apply CSS variables to container for instance override\n        if (themeObj && themeObj.colors) {\n          const cssVars = themeToCSSVars(themeObj.colors);\n          this.container.style.cssText += cssVars;\n        }\n\n        // Update preview to reflect new theme\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     * @param {string} themeName - Resolved theme name\n     */\n    _applyResolvedTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      \n      // Update container with resolved theme, but keep auto in data-theme for tracking\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      // Apply CSS variables\n      if (themeObj && themeObj.colors) {\n        const cssVars = themeToCSSVars(themeObj.colors);\n        this.container.style.cssText += cssVars;\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAutoThemeListener() {\n      if (!window.matchMedia) return;\n\n      this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n      this.autoThemeListener = (event) => {\n        const resolvedTheme = event.matches ? 'cave' : 'solar';\n        this._applyResolvedTheme(resolvedTheme);\n      };\n\n      // Use addEventListener if available (modern browsers)\n      if (this.autoThemeMediaQuery.addEventListener) {\n        this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener);\n      } else if (this.autoThemeMediaQuery.addListener) {\n        // Fallback for older browsers\n        this.autoThemeMediaQuery.addListener(this.autoThemeListener);\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAutoThemeListener() {\n      if (this.autoThemeMediaQuery && this.autoThemeListener) {\n        if (this.autoThemeMediaQuery.removeEventListener) {\n          this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener);\n        } else if (this.autoThemeMediaQuery.removeListener) {\n          // Fallback for older browsers\n          this.autoThemeMediaQuery.removeListener(this.autoThemeListener);\n        }\n        this.autoThemeMediaQuery = null;\n        this.autoThemeListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAutoThemeListener();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAutoThemeListener();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAutoThemeListener();\n // Apply the initial resolved theme\n const resolvedTheme = resolveAutoTheme('auto');\n OverType._applyGlobalResolvedTheme(resolvedTheme, customColors);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances - update container theme attribute\n document.querySelectorAll('.overtype-container').forEach(container => {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n container.setAttribute('data-theme', themeName);\n }\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n // Set the theme attribute to update the theme name\n if (themeName && typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', themeName);\n }\n // Also call refreshTheme() to handle cases where the theme name stays the same\n // but the theme object's properties have changed\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n */\n static _applyGlobalResolvedTheme(themeName, customColors = null) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all containers with resolved theme, but keep 'auto' for tracking\n document.querySelectorAll('.overtype-container').forEach(container => {\n container.setAttribute('data-theme', 'auto');\n container.setAttribute('data-resolved-theme', themeName);\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', 'auto');\n webComponent.setAttribute('data-resolved-theme', themeName);\n }\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAutoThemeListener() {\n if (!window.matchMedia) return;\n\n OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n OverType.autoThemeListener = (event) => {\n const resolvedTheme = event.matches ? 'cave' : 'solar';\n OverType._applyGlobalResolvedTheme(resolvedTheme);\n };\n\n // Use addEventListener if available (modern browsers)\n if (OverType.autoThemeMediaQuery.addEventListener) {\n OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener);\n } else if (OverType.autoThemeMediaQuery.addListener) {\n // Fallback for older browsers\n OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener);\n }\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAutoThemeListener() {\n if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) {\n if (OverType.autoThemeMediaQuery.removeEventListener) {\n OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener);\n } else if (OverType.autoThemeMediaQuery.removeListener) {\n // Fallback for older browsers\n OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener);\n }\n OverType.autoThemeMediaQuery = null;\n OverType.autoThemeListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], "mappings": ";;;;;;;;;;;;;;;AAQO,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA,EAa1B,OAAO,iBAAiB;AACtB,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,aAAa;AACrC,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,gBAAgB,WAAW;AAChC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,MAAM;AAC7B,QAAI,KAAK,cAAc;AACrB,aAAO,KAAK,aAAa,IAAI;AAAA,IAC/B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WAAW,MAAM;AACtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,WAAO,KAAK,QAAQ,YAAY,OAAK,IAAI,CAAC,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,oBAAoB,MAAM,cAAc;AAC7C,UAAM,gBAAgB,aAAa,MAAM,QAAQ,EAAE,CAAC;AACpD,UAAM,cAAc,cAAc,QAAQ,MAAM,QAAQ;AACxD,WAAO,KAAK,QAAQ,QAAQ,WAAW;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,MAAM;AACvB,WAAO,KAAK,QAAQ,oBAAoB,CAAC,OAAO,QAAQ,YAAY;AAClE,YAAM,QAAQ,OAAO;AACrB,aAAO,KAAK,KAAK,gCAAgC,MAAM,WAAW,OAAO,MAAM,KAAK;AAAA,IACtF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,oBAAoB,MAAM;AAC/B,QAAI,KAAK,MAAM,wBAAwB,GAAG;AACxC,aAAO,gCAAgC,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAC3B,WAAO,KAAK,QAAQ,eAAe,CAAC,OAAO,YAAY;AACrD,aAAO,oEAAoE,OAAO;AAAA,IACpF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAC3B,WAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,aAAO,GAAG,MAAM,uDAAuD,MAAM,WAAW,OAAO;AAAA,IACjG,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,cAAc,MAAM,gBAAgB,OAAO;AAChD,WAAO,KAAK,QAAQ,yCAAyC,CAAC,OAAO,QAAQ,SAAS,YAAY;AAChG,UAAI,eAAe;AAEjB,cAAM,YAAY,QAAQ,YAAY,MAAM;AAC5C,eAAO,GAAG,MAAM,gDAAgD,YAAY,YAAY,EAAE,KAAK,OAAO;AAAA,MACxG,OAAO;AAEL,eAAO,GAAG,MAAM,wDAAwD,OAAO,YAAY,OAAO;AAAA,MACpG;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,MAAM;AAC7B,WAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,aAAO,GAAG,MAAM,wDAAwD,MAAM,WAAW,OAAO;AAAA,IAClG,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,eAAe,MAAM;AAE1B,UAAM,iBAAiB;AACvB,QAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,aAAO,iCAAiC,IAAI;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAAM;AACrB,WAAO,KAAK,QAAQ,kBAAkB,+FAA+F;AACrI,WAAO,KAAK,QAAQ,cAAc,+FAA+F;AACjI,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,YAAY,MAAM;AAGvB,WAAO,KAAK,QAAQ,WAAC,gDAAuC,GAAC,GAAE,qFAAqF;AAIpJ,WAAO,KAAK,QAAQ,WAAC,8CAAyC,GAAC,GAAE,qFAAqF;AAEtJ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,mBAAmB,MAAM;AAE9B,WAAO,KAAK,QAAQ,WAAC,mCAAgC,GAAC,GAAE,yFAAyF;AAEjJ,WAAO,KAAK,QAAQ,WAAC,iCAA8B,GAAC,GAAE,uFAAuF;AAC7I,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAS3B,WAAO,KAAK,QAAQ,WAAC,6CAAwC,GAAC,GAAE,2FAA2F;AAAA,EAC7J;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,KAAK;AAEtB,UAAM,UAAU,IAAI,KAAK;AACzB,UAAM,QAAQ,QAAQ,YAAY;AAGlC,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,kBAAkB,cAAc,KAAK,cAAY,MAAM,WAAW,QAAQ,CAAC;AAGjF,UAAM,aAAa,QAAQ,WAAW,GAAG,KACvB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACrB,CAAC,QAAQ,SAAS,GAAG,KAAK,CAAC,QAAQ,SAAS,IAAI;AAGnE,QAAI,mBAAmB,YAAY;AACjC,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WAAW,MAAM;AACtB,WAAO,KAAK,QAAQ,uBAAuB,CAAC,OAAO,MAAM,QAAQ;AAC/D,YAAM,aAAa,UAAU,KAAK,WAAW;AAE7C,YAAM,UAAU,KAAK,YAAY,GAAG;AAEpC,aAAO,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,IAAI,0CAA0C,GAAG;AAAA,IACzJ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,8BAA8B,MAAM;AACzC,UAAM,cAAc,oBAAI,IAAI;AAC5B,QAAI,mBAAmB;AACvB,QAAI,gBAAgB;AAGpB,UAAM,mBAAmB,CAAC;AAG1B,UAAM,YAAY;AAClB,QAAI;AACJ,YAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAIlD,YAAM,aAAa,UAAU,QAAQ,UAAU,CAAC,EAAE,QAAQ,IAAI;AAC9D,YAAM,WAAW,aAAa;AAC9B,YAAM,SAAS,WAAW,UAAU,CAAC,EAAE;AACvC,uBAAiB,KAAK,EAAE,OAAO,UAAU,KAAK,OAAO,CAAC;AAAA,IACxD;AAGA,UAAM,YAAY,WAAC,6CAAwC,GAAC;AAC5D,QAAI;AACJ,UAAM,cAAc,CAAC;AAErB,YAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAClD,YAAM,YAAY,UAAU;AAC5B,YAAM,UAAU,UAAU,QAAQ,UAAU,CAAC,EAAE;AAG/C,YAAM,oBAAoB,iBAAiB;AAAA,QAAK,YAC9C,aAAa,OAAO,SAAS,WAAW,OAAO;AAAA,MACjD;AAEA,UAAI,CAAC,mBAAmB;AACtB,oBAAY,KAAK;AAAA,UACf,OAAO,UAAU,CAAC;AAAA,UAClB,OAAO,UAAU;AAAA,UACjB,WAAW,UAAU,CAAC;AAAA,UACtB,SAAS,UAAU,CAAC;AAAA,UACpB,YAAY,UAAU,CAAC;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF;AAGA,gBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC5C,gBAAY,QAAQ,cAAY;AAC9B,YAAM,cAAc,SAAS,kBAAkB;AAC/C,kBAAY,IAAI,aAAa;AAAA,QAC3B,MAAM;AAAA,QACN,UAAU,SAAS;AAAA,QACnB,WAAW,SAAS;AAAA,QACpB,SAAS,SAAS;AAAA,QAClB,YAAY,SAAS;AAAA,MACvB,CAAC;AACD,sBAAgB,cAAc,UAAU,GAAG,SAAS,KAAK,IAC1C,cACA,cAAc,UAAU,SAAS,QAAQ,SAAS,MAAM,MAAM;AAAA,IAC/E,CAAC;AAGD,oBAAgB,cAAc,QAAQ,4BAA4B,CAAC,OAAO,UAAU,QAAQ;AAC1F,YAAM,cAAc,SAAS,kBAAkB;AAC/C,kBAAY,IAAI,aAAa;AAAA,QAC3B,MAAM;AAAA,QACN,UAAU;AAAA,QACV;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAED,WAAO,EAAE,eAAe,YAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,+BAA+B,MAAM,aAAa;AAEvD,UAAM,eAAe,MAAM,KAAK,YAAY,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACjE,YAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,YAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,iBAAa,QAAQ,iBAAe;AAClC,YAAM,YAAY,YAAY,IAAI,WAAW;AAC7C,UAAI;AAEJ,UAAI,UAAU,SAAS,QAAQ;AAE7B,sBAAc,qCAAqC,UAAU,SAAS,UAAU,UAAU,OAAO,+BAA+B,UAAU,UAAU;AAAA,MACtJ,WAAW,UAAU,SAAS,QAAQ;AAEpC,YAAI,oBAAoB,UAAU;AAIlC,oBAAY,QAAQ,CAAC,gBAAgB,qBAAqB;AACxD,cAAI,kBAAkB,SAAS,gBAAgB,GAAG;AAChD,gBAAI,eAAe,SAAS,QAAQ;AAClC,oBAAM,WAAW,qCAAqC,eAAe,SAAS,UAAU,eAAe,OAAO,+BAA+B,eAAe,UAAU;AACtK,kCAAoB,kBAAkB,QAAQ,kBAAkB,QAAQ;AAAA,YAC1E;AAAA,UACF;AAAA,QACF,CAAC;AAGD,4BAAoB,KAAK,mBAAmB,iBAAiB;AAC7D,4BAAoB,KAAK,UAAU,iBAAiB;AACpD,4BAAoB,KAAK,YAAY,iBAAiB;AAItD,cAAM,aAAa,UAAU,KAAK,WAAW;AAC7C,cAAM,UAAU,KAAK,YAAY,UAAU,GAAG;AAC9C,sBAAc,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,iBAAiB,0CAA0C,UAAU,GAAG;AAAA,MACvL;AAEA,aAAO,KAAK,QAAQ,aAAa,WAAW;AAAA,IAC9C,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,oBAAoB,MAAM;AAE/B,UAAM,EAAE,eAAe,YAAY,IAAI,KAAK,8BAA8B,IAAI;AAG9E,QAAI,OAAO;AACX,WAAO,KAAK,mBAAmB,IAAI;AACnC,WAAO,KAAK,UAAU,IAAI;AAC1B,WAAO,KAAK,YAAY,IAAI;AAG5B,WAAO,KAAK,+BAA+B,MAAM,WAAW;AAE5D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAAM,gBAAgB,OAAO;AAC5C,QAAI,OAAO,KAAK,WAAW,IAAI;AAG/B,WAAO,KAAK,oBAAoB,MAAM,IAAI;AAG1C,UAAM,iBAAiB,KAAK,oBAAoB,IAAI;AACpD,QAAI;AAAgB,aAAO;AAE3B,UAAM,YAAY,KAAK,eAAe,IAAI;AAC1C,QAAI;AAAW,aAAO;AAGtB,WAAO,KAAK,YAAY,IAAI;AAC5B,WAAO,KAAK,gBAAgB,IAAI;AAChC,WAAO,KAAK,cAAc,MAAM,aAAa;AAC7C,WAAO,KAAK,gBAAgB,IAAI;AAChC,WAAO,KAAK,kBAAkB,IAAI;AAGlC,WAAO,KAAK,oBAAoB,IAAI;AAGpC,QAAI,KAAK,KAAK,MAAM,IAAI;AAGtB,aAAO;AAAA,IACT;AAEA,WAAO,QAAQ,IAAI;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,MAAM,MAAM,aAAa,IAAI,oBAAoB,OAAO,qBAAqB,gBAAgB,OAAO;AAEzG,SAAK,eAAe;AAEpB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,cAAc;AAElB,UAAM,cAAc,MAAM,IAAI,CAAC,MAAM,UAAU;AAE7C,UAAI,qBAAqB,UAAU,YAAY;AAC7C,cAAM,UAAU,KAAK,WAAW,IAAI,KAAK;AACzC,eAAO,yBAAyB,OAAO;AAAA,MACzC;AAGA,YAAM,iBAAiB;AACvB,UAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,sBAAc,CAAC;AAEf,eAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,MACnE;AAGA,UAAI,aAAa;AACf,cAAM,UAAU,KAAK,WAAW,IAAI;AACpC,cAAM,WAAW,KAAK,oBAAoB,SAAS,IAAI;AACvD,eAAO,QAAQ,YAAY,QAAQ;AAAA,MACrC;AAGA,aAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,IACnE,CAAC;AAGD,UAAM,OAAO,YAAY,KAAK,EAAE;AAGhC,WAAO,KAAK,gBAAgB,MAAM,mBAAmB;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,gBAAgB,MAAM,qBAAqB;AAEhD,QAAI,OAAO,aAAa,eAAe,CAAC,UAAU;AAEhD,aAAO,KAAK,sBAAsB,MAAM,mBAAmB;AAAA,IAC7D;AAGA,UAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,cAAU,YAAY;AAEtB,QAAI,cAAc;AAClB,QAAI,WAAW;AACf,QAAI,mBAAmB;AACvB,QAAI,cAAc;AAGlB,UAAM,WAAW,MAAM,KAAK,UAAU,QAAQ;AAE9C,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,QAAQ,SAAS,CAAC;AAGxB,UAAI,CAAC,MAAM;AAAY;AAGvB,YAAM,YAAY,MAAM,cAAc,aAAa;AACnD,UAAI,WAAW;AACb,cAAM,YAAY,UAAU;AAC5B,YAAI,UAAU,WAAW,KAAK,GAAG;AAC/B,cAAI,CAAC,aAAa;AAEhB,0BAAc;AAGd,+BAAmB,SAAS,cAAc,KAAK;AAC/C,kBAAM,cAAc,SAAS,cAAc,MAAM;AACjD,6BAAiB,YAAY,WAAW;AACxC,6BAAiB,YAAY;AAG7B,kBAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,gBAAI,MAAM;AACR,0BAAY,YAAY,YAAY,IAAI;AAAA,YAC1C;AAGA,sBAAU,aAAa,kBAAkB,MAAM,WAAW;AAG1D,6BAAiB,eAAe;AAChC,6BAAiB,YAAY;AAC7B,6BAAiB,eAAe;AAChC;AAAA,UACF,OAAO;AAGL,kBAAM,cAAc,uBAAuB,KAAK;AAChD,gBAAI,oBAAoB,eAAe,iBAAiB,cAAc;AACpE,kBAAI;AACF,sBAAM,SAAS;AAAA,kBACb,iBAAiB;AAAA,kBACjB,iBAAiB,aAAa;AAAA,gBAChC;AAGA,oBAAI,UAAU,OAAO,OAAO,SAAS,YAAY;AAC/C,0BAAQ,KAAK,kOAAkO;AAAA,gBAEjP,OAAO;AAGL,sBAAI,UAAU,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AACzD,qCAAiB,aAAa,YAAY;AAAA,kBAC5C;AAAA,gBAEF;AAAA,cACF,SAAS,OAAO;AACd,wBAAQ,KAAK,6BAA6B,KAAK;AAAA,cAEjD;AAAA,YACF;AAEA,0BAAc;AACd,+BAAmB;AACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,eAAe,oBAAoB,MAAM,YAAY,SAAS,CAAC,MAAM,cAAc,aAAa,GAAG;AACrG,cAAM,cAAc,iBAAiB,gBAAgB,iBAAiB,cAAc,MAAM;AAE1F,YAAI,iBAAiB,aAAa,SAAS,GAAG;AAC5C,2BAAiB,gBAAgB;AAAA,QACnC;AAEA,cAAM,WAAW,MAAM,YAAY,QAAQ,WAAW,GAAG;AACzD,yBAAiB,gBAAgB;AAGjC,YAAI,YAAY,YAAY,SAAS,GAAG;AACtC,sBAAY,eAAe;AAAA,QAC7B;AACA,oBAAY,eAAe;AAC3B,cAAM,OAAO;AACb;AAAA,MACF;AAGA,UAAI,WAAW;AACf,UAAI,MAAM,YAAY,OAAO;AAE3B,mBAAW,MAAM,cAAc,IAAI;AAAA,MACrC;AAEA,UAAI,UAAU;AACZ,cAAM,WAAW,SAAS,UAAU,SAAS,aAAa;AAC1D,cAAM,YAAY,SAAS,UAAU,SAAS,cAAc;AAE5D,YAAI,CAAC,YAAY,CAAC,WAAW;AAC3B,wBAAc;AACd,qBAAW;AACX;AAAA,QACF;AAEA,cAAM,UAAU,WAAW,OAAO;AAGlC,YAAI,CAAC,eAAe,aAAa,SAAS;AACxC,wBAAc,SAAS,cAAc,OAAO;AAC5C,oBAAU,aAAa,aAAa,KAAK;AACzC,qBAAW;AAAA,QACb;AAGA,cAAM,mBAAmB,CAAC;AAC1B,mBAAW,QAAQ,MAAM,YAAY;AACnC,cAAI,KAAK,aAAa,KAAK,KAAK,YAAY,MAAM,WAAW,GAAG;AAE9D,6BAAiB,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,UAC5C,WAAW,SAAS,UAAU;AAC5B;AAAA,UACF;AAAA,QACF;AAGA,yBAAiB,QAAQ,UAAQ;AAC/B,mBAAS,aAAa,MAAM,SAAS,UAAU;AAAA,QACjD,CAAC;AAGD,oBAAY,YAAY,QAAQ;AAGhC,cAAM,OAAO;AAAA,MACf,OAAO;AAEL,sBAAc;AACd,mBAAW;AAAA,MACb;AAAA,IACF;AAEA,WAAO,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,sBAAsB,MAAM,qBAAqB;AACtD,QAAI,YAAY;AAGhB,gBAAY,UAAU,QAAQ,wEAAwE,CAAC,UAAU;AAC/G,YAAM,OAAO,MAAM,MAAM,4DAA4D,KAAK,CAAC;AAC3F,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,gBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,gBAAM,gBAAgB,IAAI,MAAM,mCAAmC;AAEnE,cAAI,eAAe,eAAe;AAChC,kBAAM,cAAc,YAAY,CAAC;AACjC,kBAAM,WAAW,cAAc,CAAC;AAEhC,mBAAO,SAAS,QAAQ,4BAA4B,2BAA2B,WAAW,EAAE;AAAA,UAC9F;AACA,iBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,QAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,MACnC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,gBAAY,UAAU,QAAQ,yEAAyE,CAAC,UAAU;AAChH,YAAM,OAAO,MAAM,MAAM,6DAA6D,KAAK,CAAC;AAC5F,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,gBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,gBAAM,gBAAgB,IAAI,MAAM,oCAAoC;AAEpE,cAAI,eAAe,eAAe;AAChC,kBAAM,cAAc,YAAY,CAAC;AACjC,kBAAM,WAAW,cAAc,CAAC;AAEhC,mBAAO,SAAS,QAAQ,6BAA6B,4BAA4B,WAAW,EAAE;AAAA,UAChG;AACA,iBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,QAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,MACnC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,UAAM,iBAAiB;AACvB,gBAAY,UAAU,QAAQ,gBAAgB,CAAC,OAAO,WAAW,SAAS,eAAe;AAEvF,YAAM,QAAQ,QAAQ,MAAM,qBAAqB,KAAK,CAAC;AACvD,YAAM,cAAc,MAAM,IAAI,UAAQ;AAEpC,cAAM,OAAO,KAAK,QAAQ,sBAAsB,IAAI,EACjD,QAAQ,WAAW,GAAG;AACzB,eAAO;AAAA,MACT,CAAC,EAAE,KAAK,IAAI;AAGZ,YAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,YAAM,YAAY,OAAO,oBAAoB,IAAI,MAAM;AAGvD,UAAI,qBAAqB;AAEzB,YAAM,cAAc,uBAAuB,KAAK;AAChD,UAAI,aAAa;AACf,YAAI;AAIF,gBAAM,cAAc,YACjB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,UAAU,GAAG;AAExB,gBAAMA,UAAS,YAAY,aAAa,IAAI;AAI5C,cAAIA,WAAU,OAAOA,QAAO,SAAS,YAAY;AAC/C,oBAAQ,KAAK,4HAA4H;AAAA,UAE3I,OAAO;AAEL,gBAAIA,WAAU,OAAOA,YAAW,YAAYA,QAAO,KAAK,GAAG;AACzD,mCAAqBA;AAAA,YACvB;AAAA,UAEF;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,KAAK,6BAA6B,KAAK;AAAA,QAEjD;AAAA,MACF;AAGA,UAAI,SAAS,iCAAiC,SAAS;AAEvD,gBAAU,gCAAgC,SAAS,IAAI,kBAAkB;AACzE,gBAAU,iCAAiC,UAAU;AAErD,aAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,eAAe,MAAM,gBAAgB;AAE1C,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,aAAa;AACjB,QAAI,YAAY;AAChB,QAAI,YAAY;AAEhB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,aAAa,MAAM,CAAC,EAAE;AAC5B,UAAI,aAAa,cAAc,gBAAgB;AAC7C,oBAAY;AACZ,oBAAY;AACZ;AAAA,MACF;AACA,oBAAc,aAAa;AAAA,IAC7B;AAEA,UAAM,cAAc,MAAM,SAAS;AACnC,UAAM,UAAU,YAAY,YAAY;AAGxC,UAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,cAAc,CAAC;AAAA,QACvB,QAAQ;AAAA,QACR,SAAS,cAAc,CAAC,MAAM;AAAA,QAC9B,SAAS,cAAc,CAAC;AAAA,QACxB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,MAChF;AAAA,IACF;AAGA,UAAM,cAAc,YAAY,MAAM,KAAK,cAAc,MAAM;AAC/D,QAAI,aAAa;AACf,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,YAAY,CAAC;AAAA,QACrB,QAAQ,YAAY,CAAC;AAAA,QACrB,SAAS,YAAY,CAAC;AAAA,QACtB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,YAAY,CAAC,EAAE,SAAS,YAAY,CAAC,EAAE,SAAS;AAAA;AAAA,MAC5E;AAAA,IACF;AAGA,UAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,cAAc,CAAC;AAAA,QACvB,QAAQ,SAAS,cAAc,CAAC,CAAC;AAAA,QACjC,SAAS,cAAc,CAAC;AAAA,QACxB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,MAChF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,SAAS;AAChC,YAAQ,QAAQ,UAAU;AAAA,MACxB,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,MAAM;AAAA,MAC3C,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,SAAS,CAAC;AAAA,MAC/C,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM;AAAA,MAC1B;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,cAAc,MAAM;AACzB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,kBAAkB,oBAAI,IAAI;AAChC,QAAI,SAAS;AAEb,UAAM,SAAS,MAAM,IAAI,UAAQ;AAC/B,YAAM,QAAQ,KAAK,MAAM,KAAK,cAAc,QAAQ;AAEpD,UAAI,OAAO;AACT,cAAM,SAAS,MAAM,CAAC;AACtB,cAAM,cAAc,OAAO;AAC3B,cAAM,UAAU,MAAM,CAAC;AAGvB,YAAI,CAAC,QAAQ;AACX,0BAAgB,MAAM;AAAA,QACxB;AAGA,cAAM,iBAAiB,gBAAgB,IAAI,WAAW,KAAK,KAAK;AAChE,wBAAgB,IAAI,aAAa,aAAa;AAG9C,mBAAW,CAAC,KAAK,KAAK,iBAAiB;AACrC,cAAI,QAAQ,aAAa;AACvB,4BAAgB,OAAO,KAAK;AAAA,UAC9B;AAAA,QACF;AAEA,iBAAS;AACT,eAAO,GAAG,MAAM,GAAG,aAAa,KAAK,OAAO;AAAA,MAC9C,OAAO;AAEL,YAAI,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,MAAM,KAAK,GAAG;AAE5C,mBAAS;AACT,0BAAgB,MAAM;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,OAAO,KAAK,IAAI;AAAA,EACzB;AACF;AAAA;AA18BE,cAFW,gBAEJ,aAAY;AAAA;AAGnB,cALW,gBAKJ,mBAAkB;AAAA;AAGzB,cARW,gBAQJ,gBAAe;AAAA;AAAA;AAAA;AAsyBtB,cA9yBW,gBA8yBJ,iBAAgB;AAAA,EACrB,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AACZ;;;AClzBK,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAY,QAAQ;AAClB,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,OAAO;AACnB,UAAM,QAAQ,UAAU,SAAS,YAAY,EAAE,SAAS,KAAK;AAC7D,UAAM,SAAS,QAAQ,MAAM,UAAU,MAAM;AAE7C,QAAI,CAAC;AAAQ,aAAO;AAEpB,QAAI,WAAW;AAEf,YAAQ,MAAM,IAAI,YAAY,GAAG;AAAA,MAC/B,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,MAAM;AAAU,qBAAW;AAC/B;AAAA,MACF,KAAK;AACH,YAAI,MAAM;AAAU,qBAAW;AAC/B;AAAA,IACJ;AAEA,QAAI,UAAU;AACZ,YAAM,eAAe;AACrB,WAAK,OAAO,cAAc,UAAU,KAAK;AACzC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,EAEV;AACF;;;ACnDO,IAAM,QAAQ;AAAA,EACnB,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,MAAM;AAAA;AAAA,IACN,aAAa;AAAA;AAAA,IACb,eAAe;AAAA;AAAA,IACf,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,QAAQ;AAAA;AAAA,IACR,IAAI;AAAA;AAAA,IACJ,KAAK;AAAA;AAAA,IACL,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA;AAAA,IACR,YAAY;AAAA;AAAA,IACZ,IAAI;AAAA;AAAA,IACJ,cAAc;AAAA;AAAA,IACd,QAAQ;AAAA;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,SAAS;AAAA;AAAA,IACT,QAAQ;AAAA;AAAA,IACR,SAAS;AAAA;AAAA,IACT,SAAS;AAAA;AAAA;AAAA,IAET,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,eAAe;AAAA;AAAA,EACjB;AACF;AAKO,IAAM,OAAO;AAAA,EAClB,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,MAAM;AAAA;AAAA,IACN,aAAa;AAAA;AAAA,IACb,eAAe;AAAA;AAAA,IACf,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,QAAQ;AAAA;AAAA,IACR,IAAI;AAAA;AAAA,IACJ,KAAK;AAAA;AAAA,IACL,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA;AAAA,IACR,YAAY;AAAA;AAAA,IACZ,IAAI;AAAA;AAAA,IACJ,cAAc;AAAA;AAAA,IACd,QAAQ;AAAA;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,SAAS;AAAA;AAAA,IACT,QAAQ;AAAA;AAAA,IACR,SAAS;AAAA;AAAA,IACT,SAAS;AAAA;AAAA;AAAA,IAET,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,eAAe;AAAA;AAAA,EACjB;AACF;AAMO,IAAM,OAAO;AAAA,EAClB,MAAM;AAAA;AAAA,EAEN,QAAQ,MAAM;AAAA;AAChB;AAKO,IAAM,SAAS;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,OAAO;AAAA,EACP,MAAM;AACR;AAOO,SAAS,SAAS,OAAO;AAC9B,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AAEzC,WAAO,EAAE,GAAG,UAAU,MAAM,MAAM;AAAA,EACpC;AACA,SAAO;AACT;AAOO,SAAS,iBAAiB,WAAW;AAC1C,MAAI,cAAc,QAAQ;AACxB,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,OAAO,cAAc,OAAO,WAAW,8BAA8B,EAAE;AAC1F,SAAO,aAAa,SAAS;AAC/B;AAgBO,SAAS,eAAe,QAAQ;AACrC,QAAM,OAAO,CAAC;AACd,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAEjD,UAAM,UAAU,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC3D,SAAK,KAAK,KAAK,OAAO,KAAK,KAAK,GAAG;AAAA,EACrC;AACA,SAAO,KAAK,KAAK,IAAI;AACvB;AAQO,SAAS,WAAW,WAAW,eAAe,CAAC,GAAG;AACvD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ;AAAA,MACN,GAAG,UAAU;AAAA,MACb,GAAG;AAAA,IACL;AAAA,EACF;AACF;;;AChKO,SAAS,eAAe,UAAU,CAAC,GAAG;AAC3C,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,aAAa;AAAA;AAAA,IAEb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS,CAAC;AAAA,EACZ,IAAI;AAGJ,QAAM,eAAe,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI;AAAA;AAAA;AAAA;AAAA,UAI9C,OAAO,QAAQ,MAAM,EACpB,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AACpB,UAAM,UAAU,KAAK,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC5D,WAAO,GAAG,OAAO,KAAK,GAAG;AAAA,EAC3B,CAAC,EACA,KAAK,YAAY,CAAC;AAAA;AAAA;AAAA,MAGvB;AAGJ,QAAM,YAAY,SAAS,MAAM,SAAS,eAAe,MAAM,MAAM,IAAI;AAEzE,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAyCD,YAAY;AAAA;AAAA,QAEZ,SAAS,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAyCH,UAAU;AAAA;AAAA,6CAEc,QAAQ;AAAA,iDACJ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCASlB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;;;;;;;;;;;;;AC92BO,IAAM,UAA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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons", "themeName"] } diff --git a/dist/overtype.js.map b/dist/overtype.js.map index 86e1f97..dda5d5d 100644 --- a/dist/overtype.js.map +++ b/dist/overtype.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/overtype.js", "../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js"], - "sourcesContent": ["/**\r\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\r\n * @version 1.0.0\r\n * @license MIT\r\n */\r\n\r\nimport { MarkdownParser } from './parser.js';\r\nimport { ShortcutsManager } from './shortcuts.js';\r\nimport { generateStyles } from './styles.js';\r\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\r\nimport { Toolbar } from './toolbar.js';\r\nimport { LinkTooltip } from './link-tooltip.js';\r\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\r\n\r\n/**\r\n * Build action map from toolbar button configurations\r\n * @param {Array} buttons - Array of button config objects\r\n * @returns {Object} Map of actionId -> action function\r\n */\r\nfunction buildActionsMap(buttons) {\r\n const map = {};\r\n (buttons || []).forEach((btn) => {\r\n if (!btn || btn.name === 'separator') return;\r\n const id = btn.actionId || btn.name;\r\n if (btn.action) {\r\n map[id] = btn.action;\r\n }\r\n });\r\n return map;\r\n}\r\n\r\n/**\r\n * Normalize toolbar buttons for comparison\r\n * @param {Array|null} buttons\r\n * @returns {Array|null}\r\n */\r\nfunction normalizeButtons(buttons) {\r\n const list = buttons || defaultToolbarButtons;\r\n if (!Array.isArray(list)) return null;\r\n return list.map((btn) => ({\r\n name: btn?.name || null,\r\n actionId: btn?.actionId || btn?.name || null,\r\n icon: btn?.icon || null,\r\n title: btn?.title || null\r\n }));\r\n}\r\n\r\n/**\r\n * Determine if toolbar button configuration changed\r\n * @param {Array|null} prevButtons\r\n * @param {Array|null} nextButtons\r\n * @returns {boolean}\r\n */\r\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\r\n const prev = normalizeButtons(prevButtons);\r\n const next = normalizeButtons(nextButtons);\r\n\r\n if (prev === null || next === null) return prev !== next;\r\n if (prev.length !== next.length) return true;\r\n\r\n for (let i = 0; i < prev.length; i++) {\r\n const a = prev[i];\r\n const b = next[i];\r\n if (a.name !== b.name ||\r\n a.actionId !== b.actionId ||\r\n a.icon !== b.icon ||\r\n a.title !== b.title) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * OverType Editor Class\r\n */\r\nclass OverType {\r\n // Static properties\r\n static instances = new WeakMap();\r\n static stylesInjected = false;\r\n static globalListenersInitialized = false;\r\n static instanceCount = 0;\r\n static autoThemeMediaQuery = null; // Media query for auto theme switching\r\n static autoThemeListener = null; // Listener function for auto theme changes\r\n\r\n /**\r\n * Constructor - Always returns an array of instances\r\n * @param {string|Element|NodeList|Array} target - Target element(s)\r\n * @param {Object} options - Configuration options\r\n * @returns {Array} Array of OverType instances\r\n */\r\n constructor(target, options = {}) {\r\n // Convert target to array of elements\r\n let elements;\r\n \r\n if (typeof target === 'string') {\r\n elements = document.querySelectorAll(target);\r\n if (elements.length === 0) {\r\n throw new Error(`No elements found for selector: ${target}`);\r\n }\r\n elements = Array.from(elements);\r\n } else if (target instanceof Element) {\r\n elements = [target];\r\n } else if (target instanceof NodeList) {\r\n elements = Array.from(target);\r\n } else if (Array.isArray(target)) {\r\n elements = target;\r\n } else {\r\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\r\n }\r\n\r\n // Initialize all elements and return array\r\n const instances = elements.map(element => {\r\n // Check for existing instance\r\n if (element.overTypeInstance) {\r\n // Re-init existing instance\r\n element.overTypeInstance.reinit(options);\r\n return element.overTypeInstance;\r\n }\r\n\r\n // Create new instance\r\n const instance = Object.create(OverType.prototype);\r\n instance._init(element, options);\r\n element.overTypeInstance = instance;\r\n OverType.instances.set(element, instance);\r\n return instance;\r\n });\r\n\r\n return instances;\r\n }\r\n\r\n /**\r\n * Internal initialization\r\n * @private\r\n */\r\n _init(element, options = {}) {\r\n this.element = element;\r\n \r\n // Store the original theme option before merging\r\n this.instanceTheme = options.theme || null;\r\n \r\n // Auto theme tracking for instance-level theme\r\n this.autoThemeMediaQuery = null;\r\n this.autoThemeListener = null;\r\n \r\n this.options = this._mergeOptions(options);\r\n this.instanceId = ++OverType.instanceCount;\r\n this.initialized = false;\r\n\r\n // Inject styles if needed\r\n OverType.injectStyles();\r\n\r\n // Initialize global listeners\r\n OverType.initGlobalListeners();\r\n\r\n // Check for existing OverType DOM structure\r\n const container = element.querySelector('.overtype-container');\r\n const wrapper = element.querySelector('.overtype-wrapper');\r\n if (container || wrapper) {\r\n this._recoverFromDOM(container, wrapper);\r\n } else {\r\n this._buildFromScratch();\r\n }\r\n\r\n // Set up instance theme if provided (including auto theme listener)\r\n if (this.instanceTheme) {\r\n this.setTheme(this.instanceTheme);\r\n }\r\n\r\n // Setup shortcuts manager\r\n this.shortcuts = new ShortcutsManager(this);\r\n\r\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\r\n this._rebuildActionsMap();\r\n\r\n // Setup link tooltip\r\n this.linkTooltip = new LinkTooltip(this);\r\n\r\n // Sync scroll positions on initial render\r\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\r\n // Double requestAnimationFrame waits for browser to restore scroll position\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(() => {\r\n this.textarea.scrollTop = this.preview.scrollTop;\r\n this.textarea.scrollLeft = this.preview.scrollLeft;\r\n });\r\n });\r\n\r\n // Mark as initialized\r\n this.initialized = true;\r\n\r\n // Call onChange if provided\r\n if (this.options.onChange) {\r\n this.options.onChange(this.getValue(), this);\r\n }\r\n }\r\n\r\n /**\r\n * Merge user options with defaults\r\n * @private\r\n */\r\n _mergeOptions(options) {\r\n const defaults = {\r\n // Typography\r\n fontSize: '14px',\r\n lineHeight: 1.6,\r\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\r\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\r\n padding: '16px',\r\n \r\n // Mobile styles\r\n mobile: {\r\n fontSize: '16px', // Prevent zoom on iOS\r\n padding: '12px',\r\n lineHeight: 1.5\r\n },\r\n \r\n // Native textarea properties\r\n textareaProps: {},\r\n \r\n // Behavior\r\n autofocus: false,\r\n autoResize: false, // Auto-expand height with content\r\n minHeight: '100px', // Minimum height for autoResize mode\r\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\r\n placeholder: 'Start typing...',\r\n value: '',\r\n \r\n // Callbacks\r\n onChange: null,\r\n onKeydown: null,\r\n \r\n // Features\r\n showActiveLineRaw: false,\r\n showStats: false,\r\n toolbar: false,\r\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\r\n statsFormatter: null,\r\n smartLists: true, // Enable smart list continuation\r\n codeHighlighter: null // Per-instance code highlighter\r\n };\r\n \r\n // Remove theme and colors from options - these are now global\r\n const { theme, colors, ...cleanOptions } = options;\r\n \r\n return {\r\n ...defaults,\r\n ...cleanOptions\r\n };\r\n }\r\n\r\n /**\r\n * Recover from existing DOM structure\r\n * @private\r\n */\r\n _recoverFromDOM(container, wrapper) {\r\n // Handle old structure (wrapper only) or new structure (container + wrapper)\r\n if (container && container.classList.contains('overtype-container')) {\r\n this.container = container;\r\n this.wrapper = container.querySelector('.overtype-wrapper');\r\n } else if (wrapper) {\r\n // Old structure - just wrapper, no container\r\n this.wrapper = wrapper;\r\n // Wrap it in a container for consistency\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-container';\r\n // Use instance theme if provided, otherwise use global theme\r\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\r\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\r\n if (themeName) {\r\n this.container.setAttribute('data-theme', themeName);\r\n }\r\n \r\n // If using instance theme, apply CSS variables to container\r\n if (this.instanceTheme) {\r\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\r\n if (themeObj && themeObj.colors) {\r\n const cssVars = themeToCSSVars(themeObj.colors);\r\n this.container.style.cssText += cssVars;\r\n }\r\n }\r\n wrapper.parentNode.insertBefore(this.container, wrapper);\r\n this.container.appendChild(wrapper);\r\n }\r\n \r\n if (!this.wrapper) {\r\n // No valid structure found\r\n if (container) container.remove();\r\n if (wrapper) wrapper.remove();\r\n this._buildFromScratch();\r\n return;\r\n }\r\n \r\n this.textarea = this.wrapper.querySelector('.overtype-input');\r\n this.preview = this.wrapper.querySelector('.overtype-preview');\r\n\r\n if (!this.textarea || !this.preview) {\r\n // Partial DOM - clear and rebuild\r\n this.container.remove();\r\n this._buildFromScratch();\r\n return;\r\n }\r\n\r\n // Store reference on wrapper\r\n this.wrapper._instance = this;\r\n \r\n // Apply instance-specific styles via CSS custom properties\r\n if (this.options.fontSize) {\r\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\r\n }\r\n if (this.options.lineHeight) {\r\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\r\n }\r\n if (this.options.padding) {\r\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\r\n }\r\n\r\n // Disable autofill, spellcheck, and extensions\r\n this._configureTextarea();\r\n\r\n // Apply any new options\r\n this._applyOptions();\r\n }\r\n\r\n /**\r\n * Build editor from scratch\r\n * @private\r\n */\r\n _buildFromScratch() {\r\n // Extract any existing content\r\n const content = this._extractContent();\r\n\r\n // Clear element\r\n this.element.innerHTML = '';\r\n\r\n // Create DOM structure\r\n this._createDOM();\r\n\r\n // Set initial content\r\n if (content || this.options.value) {\r\n this.setValue(content || this.options.value);\r\n }\r\n\r\n // Apply options\r\n this._applyOptions();\r\n }\r\n\r\n /**\r\n * Extract content from element\r\n * @private\r\n */\r\n _extractContent() {\r\n // Look for existing OverType textarea\r\n const textarea = this.element.querySelector('.overtype-input');\r\n if (textarea) return textarea.value;\r\n\r\n // Use element's text content as fallback\r\n return this.element.textContent || '';\r\n }\r\n\r\n /**\r\n * Create DOM structure\r\n * @private\r\n */\r\n _createDOM() {\r\n // Create container that will hold toolbar and editor\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-container';\r\n \r\n // Set theme on container - use instance theme if provided\r\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\r\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\r\n if (themeName) {\r\n this.container.setAttribute('data-theme', themeName);\r\n }\r\n \r\n // If using instance theme, apply CSS variables to container\r\n if (this.instanceTheme) {\r\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\r\n if (themeObj && themeObj.colors) {\r\n const cssVars = themeToCSSVars(themeObj.colors);\r\n this.container.style.cssText += cssVars;\r\n }\r\n }\r\n \r\n // Create wrapper for editor\r\n this.wrapper = document.createElement('div');\r\n this.wrapper.className = 'overtype-wrapper';\r\n \r\n \r\n // Apply instance-specific styles via CSS custom properties\r\n if (this.options.fontSize) {\r\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\r\n }\r\n if (this.options.lineHeight) {\r\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\r\n }\r\n if (this.options.padding) {\r\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\r\n }\r\n \r\n this.wrapper._instance = this;\r\n\r\n // Create textarea\r\n this.textarea = document.createElement('textarea');\r\n this.textarea.className = 'overtype-input';\r\n this.textarea.placeholder = this.options.placeholder;\r\n this._configureTextarea();\r\n \r\n // Apply any native textarea properties\r\n if (this.options.textareaProps) {\r\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\r\n if (key === 'className' || key === 'class') {\r\n this.textarea.className += ' ' + value;\r\n } else if (key === 'style' && typeof value === 'object') {\r\n Object.assign(this.textarea.style, value);\r\n } else {\r\n this.textarea.setAttribute(key, value);\r\n }\r\n });\r\n }\r\n\r\n // Create preview div\r\n this.preview = document.createElement('div');\r\n this.preview.className = 'overtype-preview';\r\n this.preview.setAttribute('aria-hidden', 'true');\r\n\r\n // Assemble DOM\r\n this.wrapper.appendChild(this.textarea);\r\n this.wrapper.appendChild(this.preview);\r\n \r\n // No need to prevent link clicks - pointer-events handles this\r\n \r\n // Add wrapper to container first\r\n this.container.appendChild(this.wrapper);\r\n \r\n // Add stats bar at the end (bottom) if enabled\r\n if (this.options.showStats) {\r\n this.statsBar = document.createElement('div');\r\n this.statsBar.className = 'overtype-stats';\r\n this.container.appendChild(this.statsBar);\r\n this._updateStats();\r\n }\r\n \r\n // Add container to element\r\n this.element.appendChild(this.container);\r\n \r\n // Setup auto-resize if enabled\r\n if (this.options.autoResize) {\r\n this._setupAutoResize();\r\n } else {\r\n // Ensure auto-resize class is removed if not using auto-resize\r\n this.container.classList.remove('overtype-auto-resize');\r\n }\r\n }\r\n\r\n /**\r\n * Configure textarea attributes\r\n * @private\r\n */\r\n _configureTextarea() {\r\n this.textarea.setAttribute('autocomplete', 'off');\r\n this.textarea.setAttribute('autocorrect', 'off');\r\n this.textarea.setAttribute('autocapitalize', 'off');\r\n this.textarea.setAttribute('spellcheck', 'false');\r\n this.textarea.setAttribute('data-gramm', 'false');\r\n this.textarea.setAttribute('data-gramm_editor', 'false');\r\n this.textarea.setAttribute('data-enable-grammarly', 'false');\r\n }\r\n\r\n /**\r\n * Create and setup toolbar\r\n * @private\r\n */\r\n _createToolbar() {\r\n // Use provided toolbarButtons or default to defaultToolbarButtons\r\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\r\n\r\n this.toolbar = new Toolbar(this, { toolbarButtons });\r\n this.toolbar.create();\r\n\r\n // Store listener references for cleanup\r\n this._toolbarSelectionListener = () => {\r\n if (this.toolbar) {\r\n this.toolbar.updateButtonStates();\r\n }\r\n };\r\n this._toolbarInputListener = () => {\r\n if (this.toolbar) {\r\n this.toolbar.updateButtonStates();\r\n }\r\n };\r\n\r\n // Add listeners\r\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\r\n this.textarea.addEventListener('input', this._toolbarInputListener);\r\n }\r\n\r\n /**\r\n * Cleanup toolbar event listeners\r\n * @private\r\n */\r\n _cleanupToolbarListeners() {\r\n if (this._toolbarSelectionListener) {\r\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\r\n this._toolbarSelectionListener = null;\r\n }\r\n if (this._toolbarInputListener) {\r\n this.textarea.removeEventListener('input', this._toolbarInputListener);\r\n this._toolbarInputListener = null;\r\n }\r\n }\r\n\r\n /**\r\n * Rebuild the action map from current toolbar button configuration\r\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\r\n * @private\r\n */\r\n _rebuildActionsMap() {\r\n // Always start with default actions (shortcuts always work regardless of toolbar config)\r\n this.actionsById = buildActionsMap(defaultToolbarButtons);\r\n\r\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\r\n if (this.options.toolbarButtons) {\r\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\r\n }\r\n }\r\n\r\n /**\r\n * Apply options to the editor\r\n * @private\r\n */\r\n _applyOptions() {\r\n // Apply autofocus\r\n if (this.options.autofocus) {\r\n this.textarea.focus();\r\n }\r\n\r\n // Setup or remove auto-resize\r\n if (this.options.autoResize) {\r\n if (!this.container.classList.contains('overtype-auto-resize')) {\r\n this._setupAutoResize();\r\n }\r\n } else {\r\n // Ensure auto-resize class is removed\r\n this.container.classList.remove('overtype-auto-resize');\r\n }\r\n\r\n // Handle toolbar option changes\r\n if (this.options.toolbar && !this.toolbar) {\r\n // Create toolbar if enabled and doesn't exist\r\n this._createToolbar();\r\n } else if (!this.options.toolbar && this.toolbar) {\r\n // Destroy toolbar if disabled and exists\r\n this._cleanupToolbarListeners();\r\n this.toolbar.destroy();\r\n this.toolbar = null;\r\n }\r\n\r\n // Update preview with initial content\r\n this.updatePreview();\r\n }\r\n\r\n /**\r\n * Update preview with parsed markdown\r\n */\r\n updatePreview() {\r\n const text = this.textarea.value;\r\n const cursorPos = this.textarea.selectionStart;\r\n const activeLine = this._getCurrentLine(text, cursorPos);\r\n\r\n // Detect if we're in preview mode\r\n const isPreviewMode = this.container.dataset.mode === 'preview';\r\n\r\n // Parse markdown\r\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\r\n this.preview.innerHTML = html || 'Start typing...';\r\n \r\n // Apply code block backgrounds\r\n this._applyCodeBlockBackgrounds();\r\n \r\n // Links always have real hrefs now - no need to update them\r\n \r\n // Update stats if enabled\r\n if (this.options.showStats && this.statsBar) {\r\n this._updateStats();\r\n }\r\n \r\n // Trigger onChange callback\r\n if (this.options.onChange && this.initialized) {\r\n this.options.onChange(text, this);\r\n }\r\n }\r\n\r\n /**\r\n * Apply background styling to code blocks\r\n * @private\r\n */\r\n _applyCodeBlockBackgrounds() {\r\n // Find all code fence elements\r\n const codeFences = this.preview.querySelectorAll('.code-fence');\r\n \r\n // Process pairs of code fences\r\n for (let i = 0; i < codeFences.length - 1; i += 2) {\r\n const openFence = codeFences[i];\r\n const closeFence = codeFences[i + 1];\r\n \r\n // Get parent divs\r\n const openParent = openFence.parentElement;\r\n const closeParent = closeFence.parentElement;\r\n \r\n if (!openParent || !closeParent) continue;\r\n \r\n // Make fences display: block\r\n openFence.style.display = 'block';\r\n closeFence.style.display = 'block';\r\n \r\n // Apply class to parent divs\r\n openParent.classList.add('code-block-line');\r\n closeParent.classList.add('code-block-line');\r\n \r\n // With the new structure, there's a
     block between fences, not DIVs\r\n        // We don't need to process anything between the fences anymore\r\n        // The 
     structure already handles the content correctly\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Get current line number from cursor position\r\n     * @private\r\n     */\r\n    _getCurrentLine(text, cursorPos) {\r\n      const lines = text.substring(0, cursorPos).split('\\n');\r\n      return lines.length - 1;\r\n    }\r\n\r\n    /**\r\n     * Handle input events\r\n     * @private\r\n     */\r\n    handleInput(event) {\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Handle keydown events\r\n     * @private\r\n     */\r\n    handleKeydown(event) {\r\n      // Handle Tab key to prevent focus loss and insert spaces\r\n      if (event.key === 'Tab') {\r\n        const start = this.textarea.selectionStart;\r\n        const end = this.textarea.selectionEnd;\r\n        const value = this.textarea.value;\r\n\r\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\r\n        if (event.shiftKey && start === end) {\r\n          return;\r\n        }\r\n\r\n        event.preventDefault();\r\n\r\n        // If there's a selection, indent/outdent based on shift key\r\n        if (start !== end && event.shiftKey) {\r\n          // Outdent: remove 2 spaces from start of each selected line\r\n          const before = value.substring(0, start);\r\n          const selection = value.substring(start, end);\r\n          const after = value.substring(end);\r\n          \r\n          const lines = selection.split('\\n');\r\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\r\n          \r\n          // Try to use execCommand first to preserve undo history\r\n          if (document.execCommand) {\r\n            // Select the text that needs to be replaced\r\n            this.textarea.setSelectionRange(start, end);\r\n            document.execCommand('insertText', false, outdented);\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = before + outdented + after;\r\n            this.textarea.selectionStart = start;\r\n            this.textarea.selectionEnd = start + outdented.length;\r\n          }\r\n        } else if (start !== end) {\r\n          // Indent: add 2 spaces to start of each selected line\r\n          const before = value.substring(0, start);\r\n          const selection = value.substring(start, end);\r\n          const after = value.substring(end);\r\n          \r\n          const lines = selection.split('\\n');\r\n          const indented = lines.map(line => '  ' + line).join('\\n');\r\n          \r\n          // Try to use execCommand first to preserve undo history\r\n          if (document.execCommand) {\r\n            // Select the text that needs to be replaced\r\n            this.textarea.setSelectionRange(start, end);\r\n            document.execCommand('insertText', false, indented);\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = before + indented + after;\r\n            this.textarea.selectionStart = start;\r\n            this.textarea.selectionEnd = start + indented.length;\r\n          }\r\n        } else {\r\n          // No selection: just insert 2 spaces\r\n          // Use execCommand to preserve undo history\r\n          if (document.execCommand) {\r\n            document.execCommand('insertText', false, '  ');\r\n          } else {\r\n            // Fallback to direct manipulation\r\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\r\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\r\n          }\r\n        }\r\n        \r\n        // Trigger input event to update preview\r\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n        return;\r\n      }\r\n      \r\n      // Handle Enter key for smart list continuation\r\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\r\n        if (this.handleSmartListContinuation()) {\r\n          event.preventDefault();\r\n          return;\r\n        }\r\n      }\r\n      \r\n      // Let shortcuts manager handle other keys\r\n      const handled = this.shortcuts.handleKeydown(event);\r\n      \r\n      // Call user callback if provided\r\n      if (!handled && this.options.onKeydown) {\r\n        this.options.onKeydown(event, this);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Handle smart list continuation\r\n     * @returns {boolean} Whether the event was handled\r\n     */\r\n    handleSmartListContinuation() {\r\n      const textarea = this.textarea;\r\n      const cursorPos = textarea.selectionStart;\r\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\r\n      \r\n      if (!context || !context.inList) return false;\r\n      \r\n      // Handle empty list item (exit list)\r\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\r\n        this.deleteListMarker(context);\r\n        return true;\r\n      }\r\n      \r\n      // Handle text splitting if cursor is in middle of content\r\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\r\n        this.splitListItem(context, cursorPos);\r\n      } else {\r\n        // Just add new item after current line\r\n        this.insertNewListItem(context);\r\n      }\r\n      \r\n      // Handle numbered list renumbering\r\n      if (context.listType === 'numbered') {\r\n        this.scheduleNumberedListUpdate();\r\n      }\r\n      \r\n      return true;\r\n    }\r\n    \r\n    /**\r\n     * Delete list marker and exit list\r\n     * @private\r\n     */\r\n    deleteListMarker(context) {\r\n      // Select from line start to marker end\r\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\r\n      document.execCommand('delete');\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Insert new list item\r\n     * @private\r\n     */\r\n    insertNewListItem(context) {\r\n      const newItem = MarkdownParser.createNewListItem(context);\r\n      document.execCommand('insertText', false, '\\n' + newItem);\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Split list item at cursor position\r\n     * @private\r\n     */\r\n    splitListItem(context, cursorPos) {\r\n      // Get text after cursor\r\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\r\n      \r\n      // Delete text after cursor\r\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\r\n      document.execCommand('delete');\r\n      \r\n      // Insert new list item with remaining text\r\n      const newItem = MarkdownParser.createNewListItem(context);\r\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\r\n      \r\n      // Position cursor after new list marker\r\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\r\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\r\n      \r\n      // Trigger input event\r\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n    }\r\n    \r\n    /**\r\n     * Schedule numbered list renumbering\r\n     * @private\r\n     */\r\n    scheduleNumberedListUpdate() {\r\n      // Clear any pending update\r\n      if (this.numberUpdateTimeout) {\r\n        clearTimeout(this.numberUpdateTimeout);\r\n      }\r\n      \r\n      // Schedule update after current input cycle\r\n      this.numberUpdateTimeout = setTimeout(() => {\r\n        this.updateNumberedLists();\r\n      }, 10);\r\n    }\r\n    \r\n    /**\r\n     * Update/renumber all numbered lists\r\n     * @private\r\n     */\r\n    updateNumberedLists() {\r\n      const value = this.textarea.value;\r\n      const cursorPos = this.textarea.selectionStart;\r\n      \r\n      const newValue = MarkdownParser.renumberLists(value);\r\n      \r\n      if (newValue !== value) {\r\n        // Calculate cursor offset\r\n        let offset = 0;\r\n        const oldLines = value.split('\\n');\r\n        const newLines = newValue.split('\\n');\r\n        let charCount = 0;\r\n        \r\n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\r\n          if (oldLines[i] !== newLines[i]) {\r\n            const diff = newLines[i].length - oldLines[i].length;\r\n            if (charCount + oldLines[i].length < cursorPos) {\r\n              offset += diff;\r\n            }\r\n          }\r\n          charCount += oldLines[i].length + 1; // +1 for newline\r\n        }\r\n        \r\n        // Update textarea\r\n        this.textarea.value = newValue;\r\n        const newCursorPos = cursorPos + offset;\r\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\r\n        \r\n        // Trigger update\r\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Handle scroll events\r\n     * @private\r\n     */\r\n    handleScroll(event) {\r\n      // Sync preview scroll with textarea\r\n      this.preview.scrollTop = this.textarea.scrollTop;\r\n      this.preview.scrollLeft = this.textarea.scrollLeft;\r\n    }\r\n\r\n    /**\r\n     * Get editor content\r\n     * @returns {string} Current markdown content\r\n     */\r\n    getValue() {\r\n      return this.textarea.value;\r\n    }\r\n\r\n    /**\r\n     * Set editor content\r\n     * @param {string} value - Markdown content to set\r\n     */\r\n    setValue(value) {\r\n      this.textarea.value = value;\r\n      this.updatePreview();\r\n\r\n      // Update height if auto-resize is enabled\r\n      if (this.options.autoResize) {\r\n        this._updateAutoHeight();\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Execute an action by ID\r\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\r\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\r\n     * @param {Event|null} event - Optional event that triggered the action\r\n     * @returns {Promise} Whether the action was executed successfully\r\n     */\r\n    async performAction(actionId, event = null) {\r\n      const textarea = this.textarea;\r\n      if (!textarea) return false;\r\n\r\n      const action = this.actionsById?.[actionId];\r\n      if (!action) {\r\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\r\n        return false;\r\n      }\r\n\r\n      textarea.focus();\r\n\r\n      try {\r\n        await action({\r\n          editor: this,\r\n          getValue: () => this.getValue(),\r\n          setValue: (value) => this.setValue(value),\r\n          event\r\n        });\r\n        // Note: actions are responsible for dispatching input event\r\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\r\n        return true;\r\n      } catch (error) {\r\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\r\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\r\n          detail: { actionId, error }\r\n        }));\r\n        return false;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Get the rendered HTML of the current content\r\n     * @param {Object} options - Rendering options\r\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\r\n     * @returns {string} Rendered HTML\r\n     */\r\n    getRenderedHTML(options = {}) {\r\n      const markdown = this.getValue();\r\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\r\n\r\n      if (options.cleanHTML) {\r\n        // Remove all syntax marker spans for clean HTML export\r\n        html = html.replace(/.*?<\\/span>/g, '');\r\n        // Remove OverType-specific classes\r\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\r\n        // Clean up empty class attributes\r\n        html = html.replace(/\\sclass=\"\"/g, '');\r\n      }\r\n      \r\n      return html;\r\n    }\r\n\r\n    /**\r\n     * Get the current preview element's HTML\r\n     * This includes all syntax markers and OverType styling\r\n     * @returns {string} Current preview HTML (as displayed)\r\n     */\r\n    getPreviewHTML() {\r\n      return this.preview.innerHTML;\r\n    }\r\n    \r\n    /**\r\n     * Get clean HTML without any OverType-specific markup\r\n     * Useful for exporting to other formats or storage\r\n     * @returns {string} Clean HTML suitable for export\r\n     */\r\n    getCleanHTML() {\r\n      return this.getRenderedHTML({ cleanHTML: true });\r\n    }\r\n\r\n    /**\r\n     * Focus the editor\r\n     */\r\n    focus() {\r\n      this.textarea.focus();\r\n    }\r\n\r\n    /**\r\n     * Blur the editor\r\n     */\r\n    blur() {\r\n      this.textarea.blur();\r\n    }\r\n\r\n    /**\r\n     * Check if editor is initialized\r\n     * @returns {boolean}\r\n     */\r\n    isInitialized() {\r\n      return this.initialized;\r\n    }\r\n\r\n    /**\r\n     * Re-initialize with new options\r\n     * @param {Object} options - New options to apply\r\n     */\r\n    reinit(options = {}) {\r\n      const prevToolbarButtons = this.options?.toolbarButtons;\r\n      this.options = this._mergeOptions({ ...this.options, ...options });\r\n      const toolbarNeedsRebuild = this.toolbar &&\r\n        this.options.toolbar &&\r\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\r\n\r\n      // Rebuild action map in case toolbarButtons changed\r\n      this._rebuildActionsMap();\r\n\r\n      if (toolbarNeedsRebuild) {\r\n        this._cleanupToolbarListeners();\r\n        this.toolbar.destroy();\r\n        this.toolbar = null;\r\n        this._createToolbar();\r\n      }\r\n\r\n      this._applyOptions();\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Set theme for this instance\r\n     * @param {string|Object} theme - Theme name or custom theme object\r\n     * @returns {this} Returns this for chaining\r\n     */\r\n    setTheme(theme) {\r\n      // Clean up existing auto theme listener if any\r\n      this._cleanupAutoThemeListener();\r\n\r\n      // Update instance theme\r\n      this.instanceTheme = theme;\r\n\r\n      // Handle auto theme\r\n      if (theme === 'auto') {\r\n        this._setupAutoThemeListener();\r\n        // Apply the initial resolved theme\r\n        const resolvedTheme = resolveAutoTheme('auto');\r\n        this._applyResolvedTheme(resolvedTheme);\r\n      } else {\r\n        // Get theme object for non-auto themes\r\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\r\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n\r\n        // Update container theme attribute\r\n        if (themeName) {\r\n          this.container.setAttribute('data-theme', themeName);\r\n        }\r\n\r\n        // Apply CSS variables to container for instance override\r\n        if (themeObj && themeObj.colors) {\r\n          const cssVars = themeToCSSVars(themeObj.colors);\r\n          this.container.style.cssText += cssVars;\r\n        }\r\n\r\n        // Update preview to reflect new theme\r\n        this.updatePreview();\r\n      }\r\n\r\n      return this;\r\n    }\r\n\r\n    /**\r\n     * Apply a resolved theme name (used by auto theme)\r\n     * @private\r\n     * @param {string} themeName - Resolved theme name\r\n     */\r\n    _applyResolvedTheme(themeName) {\r\n      const themeObj = getTheme(themeName);\r\n      \r\n      // Update container with resolved theme, but keep auto in data-theme for tracking\r\n      this.container.setAttribute('data-theme', 'auto');\r\n      this.container.setAttribute('data-resolved-theme', themeName);\r\n\r\n      // Apply CSS variables\r\n      if (themeObj && themeObj.colors) {\r\n        const cssVars = themeToCSSVars(themeObj.colors);\r\n        this.container.style.cssText += cssVars;\r\n      }\r\n\r\n      // Update preview to reflect new theme\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Setup auto theme listener for instance\r\n     * @private\r\n     */\r\n    _setupAutoThemeListener() {\r\n      if (!window.matchMedia) return;\r\n\r\n      this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n      this.autoThemeListener = (event) => {\r\n        const resolvedTheme = event.matches ? 'cave' : 'solar';\r\n        this._applyResolvedTheme(resolvedTheme);\r\n      };\r\n\r\n      // Use addEventListener if available (modern browsers)\r\n      if (this.autoThemeMediaQuery.addEventListener) {\r\n        this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener);\r\n      } else if (this.autoThemeMediaQuery.addListener) {\r\n        // Fallback for older browsers\r\n        this.autoThemeMediaQuery.addListener(this.autoThemeListener);\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Clean up auto theme listener for instance\r\n     * @private\r\n     */\r\n    _cleanupAutoThemeListener() {\r\n      if (this.autoThemeMediaQuery && this.autoThemeListener) {\r\n        if (this.autoThemeMediaQuery.removeEventListener) {\r\n          this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener);\r\n        } else if (this.autoThemeMediaQuery.removeListener) {\r\n          // Fallback for older browsers\r\n          this.autoThemeMediaQuery.removeListener(this.autoThemeListener);\r\n        }\r\n        this.autoThemeMediaQuery = null;\r\n        this.autoThemeListener = null;\r\n      }\r\n    }\r\n\r\n    /**\r\n     * Set instance-specific code highlighter\r\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n     */\r\n    setCodeHighlighter(highlighter) {\r\n      this.options.codeHighlighter = highlighter;\r\n      this.updatePreview();\r\n    }\r\n\r\n    /**\r\n     * Update stats bar\r\n     * @private\r\n     */\r\n    _updateStats() {\r\n      if (!this.statsBar) return;\r\n      \r\n      const value = this.textarea.value;\r\n      const lines = value.split('\\n');\r\n      const chars = value.length;\r\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\r\n      \r\n      // Calculate line and column\r\n      const selectionStart = this.textarea.selectionStart;\r\n      const beforeCursor = value.substring(0, selectionStart);\r\n      const linesBeforeCursor = beforeCursor.split('\\n');\r\n      const currentLine = linesBeforeCursor.length;\r\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\r\n      \r\n      // Use custom formatter if provided\r\n      if (this.options.statsFormatter) {\r\n        this.statsBar.innerHTML = this.options.statsFormatter({\r\n          chars,\r\n          words,\r\n          lines: lines.length,\r\n          line: currentLine,\r\n          column: currentColumn\r\n        });\r\n      } else {\r\n        // Default format with live dot\r\n        this.statsBar.innerHTML = `\r\n          
    \r\n \r\n ${chars} chars, ${words} words, ${lines.length} lines\r\n
    \r\n
    Line ${currentLine}, Col ${currentColumn}
    \r\n `;\r\n }\r\n }\r\n \r\n /**\r\n * Setup auto-resize functionality\r\n * @private\r\n */\r\n _setupAutoResize() {\r\n // Add auto-resize class for styling\r\n this.container.classList.add('overtype-auto-resize');\r\n \r\n // Store previous height for comparison\r\n this.previousHeight = null;\r\n \r\n // Initial height update\r\n this._updateAutoHeight();\r\n \r\n // Listen for input events\r\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\r\n \r\n // Listen for window resize\r\n window.addEventListener('resize', () => this._updateAutoHeight());\r\n }\r\n \r\n /**\r\n * Update height based on scrollHeight\r\n * @private\r\n */\r\n _updateAutoHeight() {\r\n if (!this.options.autoResize) return;\r\n \r\n const textarea = this.textarea;\r\n const preview = this.preview;\r\n const wrapper = this.wrapper;\r\n \r\n // Get computed styles\r\n const computed = window.getComputedStyle(textarea);\r\n const paddingTop = parseFloat(computed.paddingTop);\r\n const paddingBottom = parseFloat(computed.paddingBottom);\r\n \r\n // Store scroll positions\r\n const scrollTop = textarea.scrollTop;\r\n \r\n // Reset height to get accurate scrollHeight\r\n textarea.style.setProperty('height', 'auto', 'important');\r\n \r\n // Calculate new height based on scrollHeight\r\n let newHeight = textarea.scrollHeight;\r\n \r\n // Apply min height constraint\r\n if (this.options.minHeight) {\r\n const minHeight = parseInt(this.options.minHeight);\r\n newHeight = Math.max(newHeight, minHeight);\r\n }\r\n \r\n // Apply max height constraint\r\n let overflow = 'hidden';\r\n if (this.options.maxHeight) {\r\n const maxHeight = parseInt(this.options.maxHeight);\r\n if (newHeight > maxHeight) {\r\n newHeight = maxHeight;\r\n overflow = 'auto';\r\n }\r\n }\r\n \r\n // Apply the new height to all elements with !important to override base styles\r\n const heightPx = newHeight + 'px';\r\n textarea.style.setProperty('height', heightPx, 'important');\r\n textarea.style.setProperty('overflow-y', overflow, 'important');\r\n \r\n preview.style.setProperty('height', heightPx, 'important');\r\n preview.style.setProperty('overflow-y', overflow, 'important');\r\n \r\n wrapper.style.setProperty('height', heightPx, 'important');\r\n \r\n // Restore scroll position\r\n textarea.scrollTop = scrollTop;\r\n preview.scrollTop = scrollTop;\r\n \r\n // Track if height changed\r\n if (this.previousHeight !== newHeight) {\r\n this.previousHeight = newHeight;\r\n // Could dispatch a custom event here if needed\r\n }\r\n }\r\n \r\n /**\r\n * Show or hide stats bar\r\n * @param {boolean} show - Whether to show stats\r\n */\r\n showStats(show) {\r\n this.options.showStats = show;\r\n\r\n if (show && !this.statsBar) {\r\n // Create stats bar (add to container, not wrapper)\r\n this.statsBar = document.createElement('div');\r\n this.statsBar.className = 'overtype-stats';\r\n this.container.appendChild(this.statsBar);\r\n this._updateStats();\r\n } else if (show && this.statsBar) {\r\n // Already visible - refresh stats (useful after changing statsFormatter)\r\n this._updateStats();\r\n } else if (!show && this.statsBar) {\r\n // Remove stats bar\r\n this.statsBar.remove();\r\n this.statsBar = null;\r\n }\r\n }\r\n \r\n /**\r\n * Show normal edit mode (overlay with markdown preview)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showNormalEditMode() {\r\n this.container.dataset.mode = 'normal';\r\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\r\n\r\n // Always sync scroll from preview to textarea\r\n requestAnimationFrame(() => {\r\n this.textarea.scrollTop = this.preview.scrollTop;\r\n this.textarea.scrollLeft = this.preview.scrollLeft;\r\n });\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Show plain textarea mode (no overlay)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showPlainTextarea() {\r\n this.container.dataset.mode = 'plain';\r\n\r\n // Update toolbar button if exists\r\n if (this.toolbar) {\r\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\r\n if (toggleBtn) {\r\n toggleBtn.classList.remove('active');\r\n toggleBtn.title = 'Show markdown preview';\r\n }\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Show preview mode (read-only view)\r\n * @returns {this} Returns this for chaining\r\n */\r\n showPreviewMode() {\r\n this.container.dataset.mode = 'preview';\r\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\r\n return this;\r\n }\r\n\r\n /**\r\n * Destroy the editor instance\r\n */\r\n destroy() {\r\n // Clean up auto theme listener\r\n this._cleanupAutoThemeListener();\r\n\r\n // Remove instance reference\r\n this.element.overTypeInstance = null;\r\n OverType.instances.delete(this.element);\r\n\r\n // Cleanup shortcuts\r\n if (this.shortcuts) {\r\n this.shortcuts.destroy();\r\n }\r\n\r\n // Remove DOM if created by us\r\n if (this.wrapper) {\r\n const content = this.getValue();\r\n this.wrapper.remove();\r\n \r\n // Restore original content\r\n this.element.textContent = content;\r\n }\r\n\r\n this.initialized = false;\r\n }\r\n\r\n // ===== Static Methods =====\r\n\r\n /**\r\n * Initialize multiple editors (static convenience method)\r\n * @param {string|Element|NodeList|Array} target - Target element(s)\r\n * @param {Object} options - Configuration options\r\n * @returns {Array} Array of OverType instances\r\n */\r\n static init(target, options = {}) {\r\n return new OverType(target, options);\r\n }\r\n\r\n /**\r\n * Initialize editors with options from data-ot-* attributes\r\n * @param {string} selector - CSS selector for target elements\r\n * @param {Object} defaults - Default options (data attrs override these)\r\n * @returns {Array} Array of OverType instances\r\n * @example\r\n * // HTML:
    \r\n * OverType.initFromData('.editor', { fontSize: '14px' });\r\n */\r\n static initFromData(selector, defaults = {}) {\r\n const elements = document.querySelectorAll(selector);\r\n return Array.from(elements).map(el => {\r\n const options = { ...defaults };\r\n\r\n // Parse data-ot-* attributes (kebab-case to camelCase)\r\n for (const attr of el.attributes) {\r\n if (attr.name.startsWith('data-ot-')) {\r\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\r\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\r\n options[key] = OverType._parseDataValue(attr.value);\r\n }\r\n }\r\n\r\n return new OverType(el, options);\r\n });\r\n }\r\n\r\n /**\r\n * Parse a data attribute value to the appropriate type\r\n * @private\r\n */\r\n static _parseDataValue(value) {\r\n if (value === 'true') return true;\r\n if (value === 'false') return false;\r\n if (value === 'null') return null;\r\n if (value !== '' && !isNaN(Number(value))) return Number(value);\r\n return value;\r\n }\r\n\r\n /**\r\n * Get instance from element\r\n * @param {Element} element - DOM element\r\n * @returns {OverType|null} OverType instance or null\r\n */\r\n static getInstance(element) {\r\n return element.overTypeInstance || OverType.instances.get(element) || null;\r\n }\r\n\r\n /**\r\n * Destroy all instances\r\n */\r\n static destroyAll() {\r\n const elements = document.querySelectorAll('[data-overtype-instance]');\r\n elements.forEach(element => {\r\n const instance = OverType.getInstance(element);\r\n if (instance) {\r\n instance.destroy();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Inject styles into the document\r\n * @param {boolean} force - Force re-injection\r\n */\r\n static injectStyles(force = false) {\r\n if (OverType.stylesInjected && !force) return;\r\n\r\n // Remove any existing OverType styles\r\n const existing = document.querySelector('style.overtype-styles');\r\n if (existing) {\r\n existing.remove();\r\n }\r\n\r\n // Generate and inject new styles with current theme\r\n const theme = OverType.currentTheme || solar;\r\n const styles = generateStyles({ theme });\r\n const styleEl = document.createElement('style');\r\n styleEl.className = 'overtype-styles';\r\n styleEl.textContent = styles;\r\n document.head.appendChild(styleEl);\r\n\r\n OverType.stylesInjected = true;\r\n }\r\n \r\n /**\r\n * Set global theme for all OverType instances\r\n * @param {string|Object} theme - Theme name or custom theme object\r\n * @param {Object} customColors - Optional color overrides\r\n */\r\n static setTheme(theme, customColors = null) {\r\n // Clean up existing auto theme listener\r\n OverType._cleanupGlobalAutoThemeListener();\r\n\r\n // Handle auto theme at global level\r\n if (theme === 'auto') {\r\n OverType._setupGlobalAutoThemeListener();\r\n // Apply the initial resolved theme\r\n const resolvedTheme = resolveAutoTheme('auto');\r\n OverType._applyGlobalResolvedTheme(resolvedTheme, customColors);\r\n } else {\r\n // Process theme\r\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\r\n\r\n // Apply custom colors if provided\r\n if (customColors) {\r\n themeObj = mergeTheme(themeObj, customColors);\r\n }\r\n\r\n // Store as current theme\r\n OverType.currentTheme = themeObj;\r\n\r\n // Re-inject styles with new theme\r\n OverType.injectStyles(true);\r\n\r\n // Update all existing instances - update container theme attribute\r\n document.querySelectorAll('.overtype-container').forEach(container => {\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n if (themeName) {\r\n container.setAttribute('data-theme', themeName);\r\n }\r\n });\r\n\r\n // Also handle any old-style wrappers without containers\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n if (!wrapper.closest('.overtype-container')) {\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n if (themeName) {\r\n wrapper.setAttribute('data-theme', themeName);\r\n }\r\n }\r\n\r\n // Trigger preview update for the instance\r\n const instance = wrapper._instance;\r\n if (instance) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components (shadow DOM instances)\r\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n // Set the theme attribute to update the theme name\r\n if (themeName && typeof webComponent.setAttribute === 'function') {\r\n webComponent.setAttribute('theme', themeName);\r\n }\r\n // Also call refreshTheme() to handle cases where the theme name stays the same\r\n // but the theme object's properties have changed\r\n if (typeof webComponent.refreshTheme === 'function') {\r\n webComponent.refreshTheme();\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Apply a resolved theme globally (used by auto theme)\r\n * @private\r\n * @param {string} themeName - Resolved theme name\r\n * @param {Object} customColors - Optional color overrides\r\n */\r\n static _applyGlobalResolvedTheme(themeName, customColors = null) {\r\n let themeObj = getTheme(themeName);\r\n\r\n // Apply custom colors if provided\r\n if (customColors) {\r\n themeObj = mergeTheme(themeObj, customColors);\r\n }\r\n\r\n // Store as current theme\r\n OverType.currentTheme = themeObj;\r\n\r\n // Re-inject styles with new theme\r\n OverType.injectStyles(true);\r\n\r\n // Update all containers with resolved theme, but keep 'auto' for tracking\r\n document.querySelectorAll('.overtype-container').forEach(container => {\r\n container.setAttribute('data-theme', 'auto');\r\n container.setAttribute('data-resolved-theme', themeName);\r\n });\r\n\r\n // Also handle any old-style wrappers without containers\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n if (!wrapper.closest('.overtype-container')) {\r\n wrapper.setAttribute('data-theme', 'auto');\r\n wrapper.setAttribute('data-resolved-theme', themeName);\r\n }\r\n\r\n // Trigger preview update for the instance\r\n const instance = wrapper._instance;\r\n if (instance) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.setAttribute === 'function') {\r\n webComponent.setAttribute('theme', 'auto');\r\n webComponent.setAttribute('data-resolved-theme', themeName);\r\n }\r\n if (typeof webComponent.refreshTheme === 'function') {\r\n webComponent.refreshTheme();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Setup global auto theme listener\r\n * @private\r\n */\r\n static _setupGlobalAutoThemeListener() {\r\n if (!window.matchMedia) return;\r\n\r\n OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n OverType.autoThemeListener = (event) => {\r\n const resolvedTheme = event.matches ? 'cave' : 'solar';\r\n OverType._applyGlobalResolvedTheme(resolvedTheme);\r\n };\r\n\r\n // Use addEventListener if available (modern browsers)\r\n if (OverType.autoThemeMediaQuery.addEventListener) {\r\n OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener);\r\n } else if (OverType.autoThemeMediaQuery.addListener) {\r\n // Fallback for older browsers\r\n OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener);\r\n }\r\n }\r\n\r\n /**\r\n * Clean up global auto theme listener\r\n * @private\r\n */\r\n static _cleanupGlobalAutoThemeListener() {\r\n if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) {\r\n if (OverType.autoThemeMediaQuery.removeEventListener) {\r\n OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener);\r\n } else if (OverType.autoThemeMediaQuery.removeListener) {\r\n // Fallback for older browsers\r\n OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener);\r\n }\r\n OverType.autoThemeMediaQuery = null;\r\n OverType.autoThemeListener = null;\r\n }\r\n }\r\n\r\n /**\r\n * Set global code highlighter for all OverType instances\r\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n */\r\n static setCodeHighlighter(highlighter) {\r\n MarkdownParser.setCodeHighlighter(highlighter);\r\n\r\n // Update all existing instances in light DOM\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n const instance = wrapper._instance;\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n // Update web components (shadow DOM instances)\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.getEditor === 'function') {\r\n const instance = webComponent.getEditor();\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Set custom syntax processor for extending markdown parsing\r\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\r\n * @example\r\n * OverType.setCustomSyntax((html) => {\r\n * // Highlight footnote references [^1]\r\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\r\n * });\r\n */\r\n static setCustomSyntax(processor) {\r\n MarkdownParser.setCustomSyntax(processor);\r\n\r\n // Update all existing instances\r\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\r\n const instance = wrapper._instance;\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n });\r\n\r\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\r\n if (typeof webComponent.getEditor === 'function') {\r\n const instance = webComponent.getEditor();\r\n if (instance && instance.updatePreview) {\r\n instance.updatePreview();\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Initialize global event listeners\r\n */\r\n static initGlobalListeners() {\r\n if (OverType.globalListenersInitialized) return;\r\n\r\n // Input event\r\n document.addEventListener('input', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleInput(e);\r\n }\r\n });\r\n\r\n // Keydown event\r\n document.addEventListener('keydown', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleKeydown(e);\r\n }\r\n });\r\n\r\n // Scroll event\r\n document.addEventListener('scroll', (e) => {\r\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\r\n const wrapper = e.target.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) instance.handleScroll(e);\r\n }\r\n }, true);\r\n\r\n // Selection change event\r\n document.addEventListener('selectionchange', (e) => {\r\n const activeElement = document.activeElement;\r\n if (activeElement && activeElement.classList.contains('overtype-input')) {\r\n const wrapper = activeElement.closest('.overtype-wrapper');\r\n const instance = wrapper?._instance;\r\n if (instance) {\r\n // Update stats bar for cursor position\r\n if (instance.options.showStats && instance.statsBar) {\r\n instance._updateStats();\r\n }\r\n // Debounce updates\r\n clearTimeout(instance._selectionTimeout);\r\n instance._selectionTimeout = setTimeout(() => {\r\n instance.updatePreview();\r\n }, 50);\r\n }\r\n }\r\n });\r\n\r\n OverType.globalListenersInitialized = true;\r\n }\r\n}\r\n\r\n// Export classes for advanced usage\r\nOverType.MarkdownParser = MarkdownParser;\r\nOverType.ShortcutsManager = ShortcutsManager;\r\n\r\n// Export theme utilities\r\nOverType.themes = { solar, cave: getTheme('cave') };\r\nOverType.getTheme = getTheme;\r\n\r\n// Set default theme\r\nOverType.currentTheme = solar;\r\n\r\n// Export for module systems\r\nexport default OverType;\r\nexport { OverType };\r\n\r\n// Export toolbar buttons for custom toolbar configurations\r\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\r\n", "/**\r\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\r\n *\r\n * Key principles:\r\n * - Every character must occupy the exact same position as in the textarea\r\n * - No font-size changes, no padding/margin on inline elements\r\n * - Markdown tokens remain visible but styled\r\n */\r\nexport class MarkdownParser {\r\n // Track link index for anchor naming\r\n static linkIndex = 0;\r\n\r\n // Global code highlighter function\r\n static codeHighlighter = null;\r\n\r\n // Custom syntax processor function\r\n static customSyntax = null;\r\n\r\n /**\r\n * Reset link index (call before parsing a new document)\r\n */\r\n static resetLinkIndex() {\r\n this.linkIndex = 0;\r\n }\r\n\r\n /**\r\n * Set global code highlighter function\r\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\r\n */\r\n static setCodeHighlighter(highlighter) {\r\n this.codeHighlighter = highlighter;\r\n }\r\n\r\n /**\r\n * Set custom syntax processor function\r\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\r\n */\r\n static setCustomSyntax(processor) {\r\n this.customSyntax = processor;\r\n }\r\n\r\n /**\r\n * Apply custom syntax processor to parsed HTML\r\n * @param {string} html - Parsed HTML line\r\n * @returns {string} HTML with custom syntax applied\r\n */\r\n static applyCustomSyntax(html) {\r\n if (this.customSyntax) {\r\n return this.customSyntax(html);\r\n }\r\n return html;\r\n }\r\n\r\n /**\r\n * Escape HTML special characters\r\n * @param {string} text - Raw text to escape\r\n * @returns {string} Escaped HTML-safe text\r\n */\r\n static escapeHtml(text) {\r\n const map = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": '''\r\n };\r\n return text.replace(/[&<>\"']/g, m => map[m]);\r\n }\r\n\r\n /**\r\n * Preserve leading spaces as non-breaking spaces\r\n * @param {string} html - HTML string\r\n * @param {string} originalLine - Original line with spaces\r\n * @returns {string} HTML with preserved indentation\r\n */\r\n static preserveIndentation(html, originalLine) {\r\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\r\n const indentation = leadingSpaces.replace(/ /g, ' ');\r\n return html.replace(/^\\s*/, indentation);\r\n }\r\n\r\n /**\r\n * Parse headers (h1-h3 only)\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed HTML with header styling\r\n */\r\n static parseHeader(html) {\r\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\r\n const level = hashes.length;\r\n return `${hashes} ${content}`;\r\n });\r\n }\r\n\r\n /**\r\n * Parse horizontal rules\r\n * @param {string} html - HTML line to parse\r\n * @returns {string|null} Parsed horizontal rule or null\r\n */\r\n static parseHorizontalRule(html) {\r\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\r\n return `
    ${html}
    `;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse blockquotes\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed blockquote\r\n */\r\n static parseBlockquote(html) {\r\n return html.replace(/^> (.+)$/, (match, content) => {\r\n return `> ${content}`;\r\n });\r\n }\r\n\r\n /**\r\n * Parse bullet lists\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed bullet list item\r\n */\r\n static parseBulletList(html) {\r\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\r\n return `${indent}
  • ${marker} ${content}
  • `;\r\n });\r\n }\r\n\r\n /**\r\n * Parse task lists (GitHub Flavored Markdown checkboxes)\r\n * @param {string} html - HTML line to parse\r\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\r\n * @returns {string} Parsed task list item\r\n */\r\n static parseTaskList(html, isPreviewMode = false) {\r\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\r\n if (isPreviewMode) {\r\n // Preview mode: render actual checkbox\r\n const isChecked = checked.toLowerCase() === 'x';\r\n return `${indent}
  • ${content}
  • `;\r\n } else {\r\n // Normal mode: keep syntax visible for alignment\r\n return `${indent}
  • - [${checked}] ${content}
  • `;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Parse numbered lists\r\n * @param {string} html - HTML line to parse\r\n * @returns {string} Parsed numbered list item\r\n */\r\n static parseNumberedList(html) {\r\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\r\n return `${indent}
  • ${marker} ${content}
  • `;\r\n });\r\n }\r\n\r\n /**\r\n * Parse code blocks (markers only)\r\n * @param {string} html - HTML line to parse\r\n * @returns {string|null} Parsed code fence or null\r\n */\r\n static parseCodeBlock(html) {\r\n // The line must start with three backticks and have no backticks after subsequent text\r\n const codeFenceRegex = /^`{3}[^`]*$/;\r\n if (codeFenceRegex.test(html)) {\r\n return `
    ${html}
    `;\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Parse bold text\r\n * @param {string} html - HTML with potential bold markdown\r\n * @returns {string} HTML with bold styling\r\n */\r\n static parseBold(html) {\r\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\r\n html = html.replace(/__(.+?)__/g, '__$1__');\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse italic text\r\n * Note: Uses lookbehind assertions - requires modern browsers\r\n * @param {string} html - HTML with potential italic markdown\r\n * @returns {string} HTML with italic styling\r\n */\r\n static parseItalic(html) {\r\n // Single asterisk - must not be adjacent to other asterisks\r\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\r\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\r\n\r\n // Single underscore - must be at word boundaries to avoid matching inside words\r\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\r\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\r\n\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse strikethrough text\r\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\r\n * @param {string} html - HTML with potential strikethrough markdown\r\n * @returns {string} HTML with strikethrough styling\r\n */\r\n static parseStrikethrough(html) {\r\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\r\n html = html.replace(/(?~~$1~~');\r\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\r\n html = html.replace(/(?~$1~');\r\n return html;\r\n }\r\n\r\n /**\r\n * Parse inline code\r\n * @param {string} html - HTML with potential code markdown\r\n * @returns {string} HTML with code styling\r\n */\r\n static parseInlineCode(html) {\r\n // Must have equal number of backticks before and after inline code\r\n //\r\n // Regex explainer:\r\n // (?$1$2$3
    ');\r\n }\r\n\r\n /**\r\n * Sanitize URL to prevent XSS attacks\r\n * @param {string} url - URL to sanitize\r\n * @returns {string} Safe URL or '#' if dangerous\r\n */\r\n static sanitizeUrl(url) {\r\n // Trim whitespace and convert to lowercase for protocol check\r\n const trimmed = url.trim();\r\n const lower = trimmed.toLowerCase();\r\n\r\n // Allow safe protocols\r\n const safeProtocols = [\r\n 'http://',\r\n 'https://',\r\n 'mailto:',\r\n 'ftp://',\r\n 'ftps://'\r\n ];\r\n\r\n // Check if URL starts with a safe protocol\r\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\r\n\r\n // Allow relative URLs (starting with / or # or no protocol)\r\n const isRelative = trimmed.startsWith('/') ||\r\n trimmed.startsWith('#') ||\r\n trimmed.startsWith('?') ||\r\n trimmed.startsWith('.') ||\r\n (!trimmed.includes(':') && !trimmed.includes('//'));\r\n\r\n // If safe protocol or relative URL, return as-is\r\n if (hasSafeProtocol || isRelative) {\r\n return url;\r\n }\r\n\r\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\r\n return '#';\r\n }\r\n\r\n /**\r\n * Parse links\r\n * @param {string} html - HTML with potential link markdown\r\n * @returns {string} HTML with link styling\r\n */\r\n static parseLinks(html) {\r\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\r\n const anchorName = `--link-${this.linkIndex++}`;\r\n // Sanitize URL to prevent XSS attacks\r\n const safeUrl = this.sanitizeUrl(url);\r\n // Use real href - pointer-events handles click prevention in normal mode\r\n return `
    [${text}](${url})`;\r\n });\r\n }\r\n\r\n /**\r\n * Identify and protect sanctuaries (code and links) before parsing\r\n * @param {string} text - Text with potential markdown\r\n * @returns {Object} Object with protected text and sanctuary map\r\n */\r\n static identifyAndProtectSanctuaries(text) {\r\n const sanctuaries = new Map();\r\n let sanctuaryCounter = 0;\r\n let protectedText = text;\r\n \r\n // Create a map to track protected regions (URLs should not be processed)\r\n const protectedRegions = [];\r\n \r\n // First, find all links and mark their URL regions as protected\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n let linkMatch;\r\n while ((linkMatch = linkRegex.exec(text)) !== null) {\r\n // Calculate the exact position of the URL part\r\n // linkMatch.index is the start of the match\r\n // We need to find where \"](\" starts, then add 2 to get URL start\r\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\r\n const urlStart = bracketPos + 2;\r\n const urlEnd = urlStart + linkMatch[2].length;\r\n protectedRegions.push({ start: urlStart, end: urlEnd });\r\n }\r\n \r\n // Now protect inline code, but skip if it's inside a protected region (URL)\r\n const codeRegex = /(? \r\n codeStart >= region.start && codeEnd <= region.end\r\n );\r\n \r\n if (!inProtectedRegion) {\r\n codeMatches.push({\r\n match: codeMatch[0],\r\n index: codeMatch.index,\r\n openTicks: codeMatch[1],\r\n content: codeMatch[2],\r\n closeTicks: codeMatch[3]\r\n });\r\n }\r\n }\r\n \r\n // Replace code matches from end to start to preserve indices\r\n codeMatches.sort((a, b) => b.index - a.index);\r\n codeMatches.forEach(codeInfo => {\r\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\r\n sanctuaries.set(placeholder, {\r\n type: 'code',\r\n original: codeInfo.match,\r\n openTicks: codeInfo.openTicks,\r\n content: codeInfo.content,\r\n closeTicks: codeInfo.closeTicks\r\n });\r\n protectedText = protectedText.substring(0, codeInfo.index) + \r\n placeholder + \r\n protectedText.substring(codeInfo.index + codeInfo.match.length);\r\n });\r\n \r\n // Then protect links - they can contain sanctuary placeholders for code but not raw code\r\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\r\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\r\n sanctuaries.set(placeholder, {\r\n type: 'link',\r\n original: match,\r\n linkText,\r\n url\r\n });\r\n return placeholder;\r\n });\r\n \r\n return { protectedText, sanctuaries };\r\n }\r\n \r\n /**\r\n * Restore and transform sanctuaries back to HTML\r\n * @param {string} html - HTML with sanctuary placeholders\r\n * @param {Map} sanctuaries - Map of sanctuaries to restore\r\n * @returns {string} HTML with sanctuaries restored and transformed\r\n */\r\n static restoreAndTransformSanctuaries(html, sanctuaries) {\r\n // Sort sanctuary placeholders by position to restore in order\r\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\r\n const indexA = html.indexOf(a);\r\n const indexB = html.indexOf(b);\r\n return indexA - indexB;\r\n });\r\n \r\n placeholders.forEach(placeholder => {\r\n const sanctuary = sanctuaries.get(placeholder);\r\n let replacement;\r\n \r\n if (sanctuary.type === 'code') {\r\n // Transform code sanctuary to HTML\r\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\r\n } else if (sanctuary.type === 'link') {\r\n // For links, we need to process the link text for markdown\r\n let processedLinkText = sanctuary.linkText;\r\n \r\n // First restore any sanctuary placeholders that were already in the link text\r\n // (e.g., inline code that was protected before the link)\r\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\r\n if (processedLinkText.includes(innerPlaceholder)) {\r\n if (innerSanctuary.type === 'code') {\r\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\r\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\r\n }\r\n }\r\n });\r\n \r\n // Now parse other markdown in the link text (bold, italic, etc)\r\n processedLinkText = this.parseStrikethrough(processedLinkText);\r\n processedLinkText = this.parseBold(processedLinkText);\r\n processedLinkText = this.parseItalic(processedLinkText);\r\n \r\n // Transform link sanctuary to HTML\r\n // URL should NOT be processed for markdown - use it as-is\r\n const anchorName = `--link-${this.linkIndex++}`;\r\n const safeUrl = this.sanitizeUrl(sanctuary.url);\r\n replacement = `[${processedLinkText}](${sanctuary.url})`;\r\n }\r\n \r\n html = html.replace(placeholder, replacement);\r\n });\r\n \r\n return html;\r\n }\r\n \r\n /**\r\n * Parse all inline elements in correct order\r\n * @param {string} text - Text with potential inline markdown\r\n * @returns {string} HTML with all inline styling\r\n */\r\n static parseInlineElements(text) {\r\n // Step 1: Identify and protect sanctuaries (code and links)\r\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\r\n \r\n // Step 2: Parse other inline elements on protected text\r\n let html = protectedText;\r\n html = this.parseStrikethrough(html);\r\n html = this.parseBold(html);\r\n html = this.parseItalic(html);\r\n \r\n // Step 3: Restore and transform sanctuaries\r\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\r\n \r\n return html;\r\n }\r\n\r\n /**\r\n * Parse a single line of markdown\r\n * @param {string} line - Raw markdown line\r\n * @returns {string} Parsed HTML line\r\n */\r\n static parseLine(line, isPreviewMode = false) {\r\n let html = this.escapeHtml(line);\r\n\r\n // Preserve indentation\r\n html = this.preserveIndentation(html, line);\r\n\r\n // Check for block elements first\r\n const horizontalRule = this.parseHorizontalRule(html);\r\n if (horizontalRule) return horizontalRule;\r\n\r\n const codeBlock = this.parseCodeBlock(html);\r\n if (codeBlock) return codeBlock;\r\n\r\n // Parse block elements\r\n html = this.parseHeader(html);\r\n html = this.parseBlockquote(html);\r\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\r\n html = this.parseBulletList(html);\r\n html = this.parseNumberedList(html);\r\n\r\n // Parse inline elements\r\n html = this.parseInlineElements(html);\r\n\r\n // Wrap in div to maintain line structure\r\n if (html.trim() === '') {\r\n // Intentionally use   for empty lines to maintain vertical spacing\r\n // This causes a 0->1 character count difference but preserves visual alignment\r\n return '
     
    ';\r\n }\r\n\r\n return `
    ${html}
    `;\r\n }\r\n\r\n /**\r\n * Parse full markdown text\r\n * @param {string} text - Full markdown text\r\n * @param {number} activeLine - Currently active line index (optional)\r\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Parsed HTML\r\n */\r\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\r\n // Reset link counter for each parse\r\n this.resetLinkIndex();\r\n\r\n const lines = text.split('\\n');\r\n let inCodeBlock = false;\r\n\r\n const parsedLines = lines.map((line, index) => {\r\n // Show raw markdown on active line if requested\r\n if (showActiveLineRaw && index === activeLine) {\r\n const content = this.escapeHtml(line) || ' ';\r\n return `
    ${content}
    `;\r\n }\r\n\r\n // Check if this line is a code fence\r\n const codeFenceRegex = /^```[^`]*$/;\r\n if (codeFenceRegex.test(line)) {\r\n inCodeBlock = !inCodeBlock;\r\n // Parse fence markers normally to get styled output\r\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\r\n }\r\n\r\n // If we're inside a code block, don't parse as markdown\r\n if (inCodeBlock) {\r\n const escaped = this.escapeHtml(line);\r\n const indented = this.preserveIndentation(escaped, line);\r\n return `
    ${indented || ' '}
    `;\r\n }\r\n\r\n // Otherwise, parse the markdown normally\r\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\r\n });\r\n\r\n // Join without newlines to prevent extra spacing\r\n const html = parsedLines.join('');\r\n\r\n // Apply post-processing for list consolidation\r\n return this.postProcessHTML(html, instanceHighlighter);\r\n }\r\n\r\n /**\r\n * Post-process HTML to consolidate lists and code blocks\r\n * @param {string} html - HTML to post-process\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\r\n */\r\n static postProcessHTML(html, instanceHighlighter) {\r\n // Check if we're in a browser environment\r\n if (typeof document === 'undefined' || !document) {\r\n // In Node.js environment - do manual post-processing\r\n return this.postProcessHTMLManual(html, instanceHighlighter);\r\n }\r\n\r\n // Parse HTML string into DOM\r\n const container = document.createElement('div');\r\n container.innerHTML = html;\r\n\r\n let currentList = null;\r\n let listType = null;\r\n let currentCodeBlock = null;\r\n let inCodeBlock = false;\r\n\r\n // Process all direct children - need to be careful with live NodeList\r\n const children = Array.from(container.children);\r\n\r\n for (let i = 0; i < children.length; i++) {\r\n const child = children[i];\r\n\r\n // Skip if child was already processed/removed\r\n if (!child.parentNode) continue;\r\n\r\n // Check for code fence start/end\r\n const codeFence = child.querySelector('.code-fence');\r\n if (codeFence) {\r\n const fenceText = codeFence.textContent;\r\n if (fenceText.startsWith('```')) {\r\n if (!inCodeBlock) {\r\n // Start of code block - keep fence visible, then add pre/code\r\n inCodeBlock = true;\r\n\r\n // Create the code block that will follow the fence\r\n currentCodeBlock = document.createElement('pre');\r\n const codeElement = document.createElement('code');\r\n currentCodeBlock.appendChild(codeElement);\r\n currentCodeBlock.className = 'code-block';\r\n\r\n // Extract language if present\r\n const lang = fenceText.slice(3).trim();\r\n if (lang) {\r\n codeElement.className = `language-${lang}`;\r\n }\r\n\r\n // Insert code block after the fence div (don't remove the fence)\r\n container.insertBefore(currentCodeBlock, child.nextSibling);\r\n\r\n // Store reference to the code element for adding content\r\n currentCodeBlock._codeElement = codeElement;\r\n currentCodeBlock._language = lang;\r\n currentCodeBlock._codeContent = '';\r\n continue;\r\n } else {\r\n // End of code block - apply highlighting if needed\r\n // Use instance highlighter if provided, otherwise fall back to global highlighter\r\n const highlighter = instanceHighlighter || this.codeHighlighter;\r\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\r\n try {\r\n const result = highlighter(\r\n currentCodeBlock._codeContent,\r\n currentCodeBlock._language || ''\r\n );\r\n\r\n // Check if result is a Promise (async highlighter)\r\n if (result && typeof result.then === 'function') {\r\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\r\n // Keep the plain text fallback that was already set\r\n } else {\r\n // Synchronous highlighter\r\n // Verify highlighter returned non-empty string\r\n if (result && typeof result === 'string' && result.trim()) {\r\n currentCodeBlock._codeElement.innerHTML = result;\r\n }\r\n // else: keep the plain text fallback that was already set\r\n }\r\n } catch (error) {\r\n console.warn('Code highlighting failed:', error);\r\n // Keep the plain text content as fallback\r\n }\r\n }\r\n\r\n inCodeBlock = false;\r\n currentCodeBlock = null;\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n // Check if we're in a code block - any div that's not a code fence\r\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\r\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\r\n // Add the line content to the code block content (for highlighting)\r\n if (currentCodeBlock._codeContent.length > 0) {\r\n currentCodeBlock._codeContent += '\\n';\r\n }\r\n // Get the actual text content, preserving spaces\r\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\r\n currentCodeBlock._codeContent += lineText;\r\n\r\n // Also add to the code element (fallback if no highlighter)\r\n if (codeElement.textContent.length > 0) {\r\n codeElement.textContent += '\\n';\r\n }\r\n codeElement.textContent += lineText;\r\n child.remove();\r\n continue;\r\n }\r\n\r\n // Check if this div contains a list item\r\n let listItem = null;\r\n if (child.tagName === 'DIV') {\r\n // Look for li inside the div\r\n listItem = child.querySelector('li');\r\n }\r\n\r\n if (listItem) {\r\n const isBullet = listItem.classList.contains('bullet-list');\r\n const isOrdered = listItem.classList.contains('ordered-list');\r\n\r\n if (!isBullet && !isOrdered) {\r\n currentList = null;\r\n listType = null;\r\n continue;\r\n }\r\n\r\n const newType = isBullet ? 'ul' : 'ol';\r\n\r\n // Start new list or continue current\r\n if (!currentList || listType !== newType) {\r\n currentList = document.createElement(newType);\r\n container.insertBefore(currentList, child);\r\n listType = newType;\r\n }\r\n\r\n // Extract and preserve indentation from the div before moving the list item\r\n const indentationNodes = [];\r\n for (const node of child.childNodes) {\r\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\r\n // This is a text node containing only non-breaking spaces (indentation)\r\n indentationNodes.push(node.cloneNode(true));\r\n } else if (node === listItem) {\r\n break; // Stop when we reach the list item\r\n }\r\n }\r\n\r\n // Add indentation to the list item\r\n indentationNodes.forEach(node => {\r\n listItem.insertBefore(node, listItem.firstChild);\r\n });\r\n\r\n // Move the list item to the current list\r\n currentList.appendChild(listItem);\r\n\r\n // Remove the now-empty div wrapper\r\n child.remove();\r\n } else {\r\n // Non-list element ends current list\r\n currentList = null;\r\n listType = null;\r\n }\r\n }\r\n\r\n return container.innerHTML;\r\n }\r\n\r\n /**\r\n * Manual post-processing for Node.js environments (without DOM)\r\n * @param {string} html - HTML to post-process\r\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\r\n * @returns {string} Post-processed HTML\r\n */\r\n static postProcessHTMLManual(html, instanceHighlighter) {\r\n let processed = html;\r\n\r\n // Process unordered lists\r\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\r\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\r\n if (divs.length > 0) {\r\n const items = divs.map(div => {\r\n // Extract indentation and list item\r\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\r\n\r\n if (indentMatch && listItemMatch) {\r\n const indentation = indentMatch[1];\r\n const listItem = listItemMatch[0];\r\n // Insert indentation at the start of the list item content\r\n return listItem.replace(/
  • /, `
  • ${indentation}`);\r\n }\r\n return listItemMatch ? listItemMatch[0] : '';\r\n }).filter(Boolean);\r\n\r\n return '
      ' + items.join('') + '
    ';\r\n }\r\n return match;\r\n });\r\n\r\n // Process ordered lists\r\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\r\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\r\n if (divs.length > 0) {\r\n const items = divs.map(div => {\r\n // Extract indentation and list item\r\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\r\n\r\n if (indentMatch && listItemMatch) {\r\n const indentation = indentMatch[1];\r\n const listItem = listItemMatch[0];\r\n // Insert indentation at the start of the list item content\r\n return listItem.replace(/
  • /, `
  • ${indentation}`);\r\n }\r\n return listItemMatch ? listItemMatch[0] : '';\r\n }).filter(Boolean);\r\n\r\n return '
      ' + items.join('') + '
    ';\r\n }\r\n return match;\r\n });\r\n\r\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\r\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\r\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\r\n // Extract the content between fences\r\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\r\n const codeContent = lines.map(line => {\r\n // Extract text from each div - content is already escaped\r\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\r\n .replace(/ /g, ' ');\r\n return text;\r\n }).join('\\n');\r\n\r\n // Extract language from the opening fence\r\n const lang = openFence.slice(3).trim();\r\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\r\n\r\n // Apply code highlighting if available\r\n let highlightedContent = codeContent;\r\n // Use instance highlighter if provided, otherwise fall back to global highlighter\r\n const highlighter = instanceHighlighter || this.codeHighlighter;\r\n if (highlighter) {\r\n try {\r\n // CRITICAL: Decode HTML entities before passing to highlighter\r\n // In the DOM path, textContent automatically decodes entities.\r\n // In the manual path, we need to decode explicitly to avoid double-escaping.\r\n const decodedCode = codeContent\r\n .replace(/"/g, '\"')\r\n .replace(/'/g, \"'\")\r\n .replace(/</g, '<')\r\n .replace(/>/g, '>')\r\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\r\n\r\n const result = highlighter(decodedCode, lang);\r\n\r\n // Check if result is a Promise (async highlighter)\r\n // Note: In Node.js context, we can't easily defer rendering, so we warn\r\n if (result && typeof result.then === 'function') {\r\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\r\n // Fall back to escaped content\r\n } else {\r\n // Synchronous highlighter - verify returned non-empty string\r\n if (result && typeof result === 'string' && result.trim()) {\r\n highlightedContent = result;\r\n }\r\n // else: keep the escaped codeContent as fallback\r\n }\r\n } catch (error) {\r\n console.warn('Code highlighting failed:', error);\r\n // Fall back to original content\r\n }\r\n }\r\n\r\n // Keep fence markers visible as separate divs, with pre/code block between them\r\n let result = `
    ${openFence}
    `;\r\n // Use highlighted content if available, otherwise use escaped content\r\n result += `
    ${highlightedContent}
    `;\r\n result += `
    ${closeFence}
    `;\r\n\r\n return result;\r\n });\r\n\r\n return processed;\r\n }\r\n\r\n /**\r\n * List pattern definitions\r\n */\r\n static LIST_PATTERNS = {\r\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\r\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\r\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\r\n };\r\n\r\n /**\r\n * Get list context at cursor position\r\n * @param {string} text - Full text content\r\n * @param {number} cursorPosition - Current cursor position\r\n * @returns {Object} List context information\r\n */\r\n static getListContext(text, cursorPosition) {\r\n // Find the line containing the cursor\r\n const lines = text.split('\\n');\r\n let currentPos = 0;\r\n let lineIndex = 0;\r\n let lineStart = 0;\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const lineLength = lines[i].length;\r\n if (currentPos + lineLength >= cursorPosition) {\r\n lineIndex = i;\r\n lineStart = currentPos;\r\n break;\r\n }\r\n currentPos += lineLength + 1; // +1 for newline\r\n }\r\n\r\n const currentLine = lines[lineIndex];\r\n const lineEnd = lineStart + currentLine.length;\r\n\r\n // Check for checkbox first (most specific)\r\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\r\n if (checkboxMatch) {\r\n return {\r\n inList: true,\r\n listType: 'checkbox',\r\n indent: checkboxMatch[1],\r\n marker: '-',\r\n checked: checkboxMatch[2] === 'x',\r\n content: checkboxMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\r\n };\r\n }\r\n\r\n // Check for bullet list\r\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\r\n if (bulletMatch) {\r\n return {\r\n inList: true,\r\n listType: 'bullet',\r\n indent: bulletMatch[1],\r\n marker: bulletMatch[2],\r\n content: bulletMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\r\n };\r\n }\r\n\r\n // Check for numbered list\r\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\r\n if (numberedMatch) {\r\n return {\r\n inList: true,\r\n listType: 'numbered',\r\n indent: numberedMatch[1],\r\n marker: parseInt(numberedMatch[2]),\r\n content: numberedMatch[3],\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\r\n };\r\n }\r\n\r\n // Not in a list\r\n return {\r\n inList: false,\r\n listType: null,\r\n indent: '',\r\n marker: null,\r\n content: currentLine,\r\n lineStart,\r\n lineEnd,\r\n markerEndPos: lineStart\r\n };\r\n }\r\n\r\n /**\r\n * Create a new list item based on context\r\n * @param {Object} context - List context from getListContext\r\n * @returns {string} New list item text\r\n */\r\n static createNewListItem(context) {\r\n switch (context.listType) {\r\n case 'bullet':\r\n return `${context.indent}${context.marker} `;\r\n case 'numbered':\r\n return `${context.indent}${context.marker + 1}. `;\r\n case 'checkbox':\r\n return `${context.indent}- [ ] `;\r\n default:\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Renumber all numbered lists in text\r\n * @param {string} text - Text containing numbered lists\r\n * @returns {string} Text with renumbered lists\r\n */\r\n static renumberLists(text) {\r\n const lines = text.split('\\n');\r\n const numbersByIndent = new Map();\r\n let inList = false;\r\n\r\n const result = lines.map(line => {\r\n const match = line.match(this.LIST_PATTERNS.numbered);\r\n\r\n if (match) {\r\n const indent = match[1];\r\n const indentLevel = indent.length;\r\n const content = match[3];\r\n\r\n // If we weren't in a list or indent changed, reset lower levels\r\n if (!inList) {\r\n numbersByIndent.clear();\r\n }\r\n\r\n // Get the next number for this indent level\r\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\r\n numbersByIndent.set(indentLevel, currentNumber);\r\n\r\n // Clear deeper indent levels\r\n for (const [level] of numbersByIndent) {\r\n if (level > indentLevel) {\r\n numbersByIndent.delete(level);\r\n }\r\n }\r\n\r\n inList = true;\r\n return `${indent}${currentNumber}. ${content}`;\r\n } else {\r\n // Not a numbered list item\r\n if (line.trim() === '' || !line.match(/^\\s/)) {\r\n // Empty line or non-indented line breaks the list\r\n inList = false;\r\n numbersByIndent.clear();\r\n }\r\n return line;\r\n }\r\n });\r\n\r\n return result.join('\\n');\r\n }\r\n}\r\n", "/**\r\n * Keyboard shortcuts handler for OverType editor\r\n * Delegates to editor.performAction for consistent behavior\r\n */\r\n\r\n/**\r\n * ShortcutsManager - Handles keyboard shortcuts for the editor\r\n */\r\nexport class ShortcutsManager {\r\n constructor(editor) {\r\n this.editor = editor;\r\n }\r\n\r\n /**\r\n * Handle keydown events - called by OverType\r\n * @param {KeyboardEvent} event - The keyboard event\r\n * @returns {boolean} Whether the event was handled\r\n */\r\n handleKeydown(event) {\r\n const isMac = navigator.platform.toLowerCase().includes('mac');\r\n const modKey = isMac ? event.metaKey : event.ctrlKey;\r\n\r\n if (!modKey) return false;\r\n\r\n let actionId = null;\r\n\r\n switch (event.key.toLowerCase()) {\r\n case 'b':\r\n if (!event.shiftKey) actionId = 'toggleBold';\r\n break;\r\n case 'i':\r\n if (!event.shiftKey) actionId = 'toggleItalic';\r\n break;\r\n case 'k':\r\n if (!event.shiftKey) actionId = 'insertLink';\r\n break;\r\n case '7':\r\n if (event.shiftKey) actionId = 'toggleNumberedList';\r\n break;\r\n case '8':\r\n if (event.shiftKey) actionId = 'toggleBulletList';\r\n break;\r\n }\r\n\r\n if (actionId) {\r\n event.preventDefault();\r\n this.editor.performAction(actionId, event);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Cleanup\r\n */\r\n destroy() {\r\n // Nothing to clean up since we don't add our own listener\r\n }\r\n}\r\n", "/**\r\n * Built-in themes for OverType editor\r\n * Each theme provides a complete color palette for the editor\r\n */\r\n\r\n/**\r\n * Solar theme - Light, warm and bright\r\n */\r\nexport const solar = {\r\n name: 'solar',\r\n colors: {\r\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\r\n bgSecondary: '#ffffff', // White - editor background\r\n text: '#0d3b66', // Yale Blue - main text\r\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\r\n textSecondary: '#5a7a9b', // Muted blue - secondary text\r\n h1: '#f95738', // Tomato - h1 headers\r\n h2: '#ee964b', // Sandy Brown - h2 headers\r\n h3: '#3d8a51', // Forest green - h3 headers\r\n strong: '#ee964b', // Sandy Brown - bold text\r\n em: '#f95738', // Tomato - italic text\r\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\r\n link: '#0d3b66', // Yale Blue - links\r\n code: '#0d3b66', // Yale Blue - inline code\r\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\r\n blockquote: '#5a7a9b', // Muted blue - blockquotes\r\n hr: '#5a7a9b', // Muted blue - horizontal rules\r\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\r\n syntax: '#999999', // Gray - syntax highlighting fallback\r\n cursor: '#f95738', // Tomato - cursor\r\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\r\n listMarker: '#ee964b', // Sandy Brown - list markers\r\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\r\n border: '#e0e0e0', // Light gray - borders\r\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\r\n primary: '#0d3b66', // Yale Blue - primary accent\r\n // Toolbar colors\r\n toolbarBg: '#ffffff', // White - toolbar background\r\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\r\n toolbarHover: '#f5f5f5', // Light gray - hover background\r\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\r\n }\r\n};\r\n\r\n/**\r\n * Cave theme - Dark ocean depths\r\n */\r\nexport const cave = {\r\n name: 'cave',\r\n colors: {\r\n bgPrimary: '#141E26', // Deep ocean - main background\r\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\r\n text: '#c5dde8', // Light blue-gray - main text\r\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\r\n textSecondary: '#9fcfec', // Brighter blue - secondary text\r\n h1: '#d4a5ff', // Rich lavender - h1 headers\r\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\r\n h3: '#9fcfec', // Brighter blue - h3 headers\r\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\r\n em: '#9fcfec', // Brighter blue - italic text\r\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\r\n link: '#9fcfec', // Brighter blue - links\r\n code: '#c5dde8', // Light blue-gray - inline code\r\n codeBg: '#1a232b', // Very dark blue - code background\r\n blockquote: '#9fcfec', // Brighter blue - same as italic\r\n hr: '#c5dde8', // Light blue-gray - horizontal rules\r\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\r\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\r\n cursor: '#f26419', // Orange Pantone - cursor\r\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\r\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\r\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\r\n border: '#2a3f52', // Dark blue-gray - borders\r\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\r\n primary: '#9fcfec', // Brighter blue - primary accent\r\n // Toolbar colors for dark theme\r\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\r\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\r\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\r\n toolbarActive: '#2a3f52', // Even lighter - active button background\r\n }\r\n};\r\n\r\n/**\r\n * Auto theme - Automatically switches between solar and cave based on system preference\r\n * This is a special marker theme that triggers automatic theme switching\r\n */\r\nexport const auto = {\r\n name: 'auto',\r\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\r\n colors: solar.colors // Default to solar colors for initial render\r\n};\r\n\r\n/**\r\n * Default themes registry\r\n */\r\nexport const themes = {\r\n solar,\r\n cave,\r\n auto,\r\n // Aliases for backward compatibility\r\n light: solar,\r\n dark: cave\r\n};\r\n\r\n/**\r\n * Get theme by name or return custom theme object\r\n * @param {string|Object} theme - Theme name or custom theme object\r\n * @returns {Object} Theme configuration\r\n */\r\nexport function getTheme(theme) {\r\n if (typeof theme === 'string') {\r\n const themeObj = themes[theme] || themes.solar;\r\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\r\n return { ...themeObj, name: theme };\r\n }\r\n return theme;\r\n}\r\n\r\n/**\r\n * Resolve auto theme to actual theme based on system color scheme preference\r\n * @param {string} themeName - Theme name to resolve\r\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\r\n */\r\nexport function resolveAutoTheme(themeName) {\r\n if (themeName !== 'auto') {\r\n return themeName;\r\n }\r\n\r\n // Check for system dark mode preference\r\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n return isDarkMode ? 'cave' : 'solar';\r\n}\r\n\r\n/**\r\n * Get the current system color scheme preference\r\n * @returns {string} 'dark' or 'light'\r\n */\r\nexport function getSystemColorScheme() {\r\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n return isDarkMode ? 'dark' : 'light';\r\n}\r\n\r\n/**\r\n * Apply theme colors to CSS variables\r\n * @param {Object} colors - Theme colors object\r\n * @returns {string} CSS custom properties string\r\n */\r\nexport function themeToCSSVars(colors) {\r\n const vars = [];\r\n for (const [key, value] of Object.entries(colors)) {\r\n // Convert camelCase to kebab-case\r\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n vars.push(`--${varName}: ${value};`);\r\n }\r\n return vars.join('\\n');\r\n}\r\n\r\n/**\r\n * Merge custom colors with base theme\r\n * @param {Object} baseTheme - Base theme object\r\n * @param {Object} customColors - Custom color overrides\r\n * @returns {Object} Merged theme object\r\n */\r\nexport function mergeTheme(baseTheme, customColors = {}) {\r\n return {\r\n ...baseTheme,\r\n colors: {\r\n ...baseTheme.colors,\r\n ...customColors\r\n }\r\n };\r\n}", "/**\r\n * CSS styles for OverType editor\r\n * Embedded in JavaScript to ensure single-file distribution\r\n */\r\n\r\nimport { themeToCSSVars } from './themes.js';\r\n\r\n/**\r\n * Generate the complete CSS for the editor\r\n * @param {Object} options - Configuration options\r\n * @returns {string} Complete CSS string\r\n */\r\nexport function generateStyles(options = {}) {\r\n const {\r\n fontSize = '14px',\r\n lineHeight = 1.6,\r\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\r\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\r\n padding = '20px',\r\n theme = null,\r\n mobile = {}\r\n } = options;\r\n\r\n // Generate mobile overrides\r\n const mobileStyles = Object.keys(mobile).length > 0 ? `\r\n @media (max-width: 640px) {\r\n .overtype-wrapper .overtype-input,\r\n .overtype-wrapper .overtype-preview {\r\n ${Object.entries(mobile)\r\n .map(([prop, val]) => {\r\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\r\n return `${cssProp}: ${val} !important;`;\r\n })\r\n .join('\\n ')}\r\n }\r\n }\r\n ` : '';\r\n\r\n // Generate theme variables if provided\r\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\r\n\r\n return `\r\n /* OverType Editor Styles */\r\n \r\n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\r\n .overtype-container * {\r\n /* Box model - these commonly leak */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: 0 !important;\r\n \r\n /* Layout - these can break our layout */\r\n /* Don't reset position - it breaks dropdowns */\r\n float: none !important;\r\n clear: none !important;\r\n \r\n /* Typography - only reset decorative aspects */\r\n text-decoration: none !important;\r\n text-transform: none !important;\r\n letter-spacing: normal !important;\r\n \r\n /* Visual effects that can interfere */\r\n box-shadow: none !important;\r\n text-shadow: none !important;\r\n \r\n /* Ensure box-sizing is consistent */\r\n box-sizing: border-box !important;\r\n \r\n /* Keep inheritance for these */\r\n /* font-family, color, line-height, font-size - inherit */\r\n }\r\n \r\n /* Container base styles after reset */\r\n .overtype-container {\r\n display: flex !important;\r\n flex-direction: column !important;\r\n width: 100% !important;\r\n height: 100% !important;\r\n position: relative !important; /* Override reset - needed for absolute children */\r\n overflow: visible !important; /* Allow dropdown to overflow container */\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\r\n text-align: left !important;\r\n ${themeVars ? `\r\n /* Theme Variables */\r\n ${themeVars}` : ''}\r\n }\r\n \r\n /* Force left alignment for all elements in the editor */\r\n .overtype-container .overtype-wrapper * {\r\n text-align: left !important;\r\n }\r\n \r\n /* Auto-resize mode styles */\r\n .overtype-container.overtype-auto-resize {\r\n height: auto !important;\r\n }\r\n\r\n .overtype-container.overtype-auto-resize .overtype-wrapper {\r\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\r\n height: auto !important;\r\n min-height: 60px !important;\r\n overflow: visible !important;\r\n }\r\n \r\n .overtype-wrapper {\r\n position: relative !important; /* Override reset - needed for absolute children */\r\n width: 100% !important;\r\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\r\n min-height: 60px !important; /* Minimum usable height */\r\n overflow: hidden !important;\r\n background: var(--bg-secondary, #ffffff) !important;\r\n z-index: 1; /* Below toolbar and dropdown */\r\n }\r\n\r\n /* Critical alignment styles - must be identical for both layers */\r\n .overtype-wrapper .overtype-input,\r\n .overtype-wrapper .overtype-preview {\r\n /* Positioning - must be identical */\r\n position: absolute !important; /* Override reset - required for overlay */\r\n top: 0 !important;\r\n left: 0 !important;\r\n width: 100% !important;\r\n height: 100% !important;\r\n \r\n /* Font properties - any difference breaks alignment */\r\n font-family: ${fontFamily} !important;\r\n font-variant-ligatures: none !important; /* keep metrics stable for code */\r\n font-size: var(--instance-font-size, ${fontSize}) !important;\r\n line-height: var(--instance-line-height, ${lineHeight}) !important;\r\n font-weight: normal !important;\r\n font-style: normal !important;\r\n font-variant: normal !important;\r\n font-stretch: normal !important;\r\n font-kerning: none !important;\r\n font-feature-settings: normal !important;\r\n \r\n /* Box model - must match exactly */\r\n padding: var(--instance-padding, ${padding}) !important;\r\n margin: 0 !important;\r\n border: none !important;\r\n outline: none !important;\r\n box-sizing: border-box !important;\r\n \r\n /* Text layout - critical for character positioning */\r\n white-space: pre-wrap !important;\r\n word-wrap: break-word !important;\r\n word-break: normal !important;\r\n overflow-wrap: break-word !important;\r\n tab-size: 2 !important;\r\n -moz-tab-size: 2 !important;\r\n text-align: left !important;\r\n text-indent: 0 !important;\r\n letter-spacing: normal !important;\r\n word-spacing: normal !important;\r\n \r\n /* Text rendering */\r\n text-transform: none !important;\r\n text-rendering: auto !important;\r\n -webkit-font-smoothing: auto !important;\r\n -webkit-text-size-adjust: 100% !important;\r\n \r\n /* Direction and writing */\r\n direction: ltr !important;\r\n writing-mode: horizontal-tb !important;\r\n unicode-bidi: normal !important;\r\n text-orientation: mixed !important;\r\n \r\n /* Visual effects that could shift perception */\r\n text-shadow: none !important;\r\n filter: none !important;\r\n transform: none !important;\r\n zoom: 1 !important;\r\n \r\n /* Vertical alignment */\r\n vertical-align: baseline !important;\r\n \r\n /* Size constraints */\r\n min-width: 0 !important;\r\n min-height: 0 !important;\r\n max-width: none !important;\r\n max-height: none !important;\r\n \r\n /* Overflow */\r\n overflow-y: auto !important;\r\n overflow-x: auto !important;\r\n /* overscroll-behavior removed to allow scroll-through to parent */\r\n scrollbar-width: auto !important;\r\n scrollbar-gutter: auto !important;\r\n \r\n /* Animation/transition - disabled to prevent movement */\r\n animation: none !important;\r\n transition: none !important;\r\n }\r\n\r\n /* Input layer styles */\r\n .overtype-wrapper .overtype-input {\r\n /* Layer positioning */\r\n z-index: 1 !important;\r\n \r\n /* Text visibility */\r\n color: transparent !important;\r\n caret-color: var(--cursor, #f95738) !important;\r\n background-color: transparent !important;\r\n \r\n /* Textarea-specific */\r\n resize: none !important;\r\n appearance: none !important;\r\n -webkit-appearance: none !important;\r\n -moz-appearance: none !important;\r\n \r\n /* Prevent mobile zoom on focus */\r\n touch-action: manipulation !important;\r\n \r\n /* Disable autofill and spellcheck */\r\n autocomplete: off !important;\r\n autocorrect: off !important;\r\n autocapitalize: off !important;\r\n spellcheck: false !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-input::selection {\r\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\r\n }\r\n\r\n /* Preview layer styles */\r\n .overtype-wrapper .overtype-preview {\r\n /* Layer positioning */\r\n z-index: 0 !important;\r\n pointer-events: none !important;\r\n color: var(--text, #0d3b66) !important;\r\n background-color: transparent !important;\r\n \r\n /* Prevent text selection */\r\n user-select: none !important;\r\n -webkit-user-select: none !important;\r\n -moz-user-select: none !important;\r\n -ms-user-select: none !important;\r\n }\r\n\r\n /* Defensive styles for preview child divs */\r\n .overtype-wrapper .overtype-preview div {\r\n /* Reset any inherited styles */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n border: none !important;\r\n text-align: left !important;\r\n text-indent: 0 !important;\r\n display: block !important;\r\n position: static !important;\r\n transform: none !important;\r\n min-height: 0 !important;\r\n max-height: none !important;\r\n line-height: inherit !important;\r\n font-size: inherit !important;\r\n font-family: inherit !important;\r\n }\r\n\r\n /* Markdown element styling - NO SIZE CHANGES */\r\n .overtype-wrapper .overtype-preview .header {\r\n font-weight: bold !important;\r\n }\r\n\r\n /* Header colors */\r\n .overtype-wrapper .overtype-preview .h1 { \r\n color: var(--h1, #f95738) !important; \r\n }\r\n .overtype-wrapper .overtype-preview .h2 { \r\n color: var(--h2, #ee964b) !important; \r\n }\r\n .overtype-wrapper .overtype-preview .h3 { \r\n color: var(--h3, #3d8a51) !important; \r\n }\r\n\r\n /* Semantic headers - flatten in edit mode */\r\n .overtype-wrapper .overtype-preview h1,\r\n .overtype-wrapper .overtype-preview h2,\r\n .overtype-wrapper .overtype-preview h3 {\r\n font-size: inherit !important;\r\n font-weight: bold !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n display: inline !important;\r\n line-height: inherit !important;\r\n }\r\n\r\n /* Header colors for semantic headers */\r\n .overtype-wrapper .overtype-preview h1 { \r\n color: var(--h1, #f95738) !important; \r\n }\r\n .overtype-wrapper .overtype-preview h2 { \r\n color: var(--h2, #ee964b) !important; \r\n }\r\n .overtype-wrapper .overtype-preview h3 { \r\n color: var(--h3, #3d8a51) !important; \r\n }\r\n\r\n /* Lists - remove styling in edit mode */\r\n .overtype-wrapper .overtype-preview ul,\r\n .overtype-wrapper .overtype-preview ol {\r\n list-style: none !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n display: block !important; /* Lists need to be block for line breaks */\r\n }\r\n\r\n .overtype-wrapper .overtype-preview li {\r\n display: block !important; /* Each item on its own line */\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n /* Don't set list-style here - let ul/ol control it */\r\n }\r\n\r\n /* Bold text */\r\n .overtype-wrapper .overtype-preview strong {\r\n color: var(--strong, #ee964b) !important;\r\n font-weight: bold !important;\r\n }\r\n\r\n /* Italic text */\r\n .overtype-wrapper .overtype-preview em {\r\n color: var(--em, #f95738) !important;\r\n text-decoration-color: var(--em, #f95738) !important;\r\n text-decoration-thickness: 1px !important;\r\n font-style: italic !important;\r\n }\r\n\r\n /* Strikethrough text */\r\n .overtype-wrapper .overtype-preview del {\r\n color: var(--del, #ee964b) !important;\r\n text-decoration: line-through !important;\r\n text-decoration-color: var(--del, #ee964b) !important;\r\n text-decoration-thickness: 1px !important;\r\n }\r\n\r\n /* Inline code */\r\n .overtype-wrapper .overtype-preview code {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n color: var(--code, #0d3b66) !important;\r\n padding: 0 !important;\r\n border-radius: 2px !important;\r\n font-family: inherit !important;\r\n font-size: inherit !important;\r\n line-height: inherit !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Code blocks - consolidated pre blocks */\r\n .overtype-wrapper .overtype-preview pre {\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n border-radius: 4px !important;\r\n overflow-x: auto !important;\r\n }\r\n \r\n /* Code block styling in normal mode - yellow background */\r\n .overtype-wrapper .overtype-preview pre.code-block {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\r\n }\r\n\r\n /* Code inside pre blocks - remove background */\r\n .overtype-wrapper .overtype-preview pre code {\r\n background: transparent !important;\r\n color: var(--code, #0d3b66) !important;\r\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\r\n }\r\n\r\n /* Blockquotes */\r\n .overtype-wrapper .overtype-preview .blockquote {\r\n color: var(--blockquote, #5a7a9b) !important;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n border: none !important;\r\n }\r\n\r\n /* Links */\r\n .overtype-wrapper .overtype-preview a {\r\n color: var(--link, #0d3b66) !important;\r\n text-decoration: underline !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-preview a:hover {\r\n text-decoration: underline !important;\r\n color: var(--link, #0d3b66) !important;\r\n }\r\n\r\n /* Lists - no list styling */\r\n .overtype-wrapper .overtype-preview ul,\r\n .overtype-wrapper .overtype-preview ol {\r\n list-style: none !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n\r\n /* Horizontal rules */\r\n .overtype-wrapper .overtype-preview hr {\r\n border: none !important;\r\n color: var(--hr, #5a7a9b) !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n .overtype-wrapper .overtype-preview .hr-marker {\r\n color: var(--hr, #5a7a9b) !important;\r\n opacity: 0.6 !important;\r\n }\r\n\r\n /* Code fence markers - with background when not in code block */\r\n .overtype-wrapper .overtype-preview .code-fence {\r\n color: var(--code, #0d3b66) !important;\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n }\r\n \r\n /* Code block lines - background for entire code block */\r\n .overtype-wrapper .overtype-preview .code-block-line {\r\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\r\n }\r\n \r\n /* Remove background from code fence when inside code block line */\r\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\r\n background: transparent !important;\r\n }\r\n\r\n /* Raw markdown line */\r\n .overtype-wrapper .overtype-preview .raw-line {\r\n color: var(--raw-line, #5a7a9b) !important;\r\n font-style: normal !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Syntax markers */\r\n .overtype-wrapper .overtype-preview .syntax-marker {\r\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\r\n opacity: 0.7 !important;\r\n }\r\n\r\n /* List markers */\r\n .overtype-wrapper .overtype-preview .list-marker {\r\n color: var(--list-marker, #ee964b) !important;\r\n }\r\n\r\n /* Stats bar */\r\n \r\n /* Stats bar - positioned by flexbox */\r\n .overtype-stats {\r\n height: 40px !important;\r\n padding: 0 20px !important;\r\n background: #f8f9fa !important;\r\n border-top: 1px solid #e0e0e0 !important;\r\n display: flex !important;\r\n justify-content: space-between !important;\r\n align-items: center !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\r\n font-size: 0.85rem !important;\r\n color: #666 !important;\r\n flex-shrink: 0 !important; /* Don't shrink */\r\n z-index: 10001 !important; /* Above link tooltip */\r\n position: relative !important; /* Enable z-index */\r\n }\r\n \r\n /* Dark theme stats bar */\r\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\r\n background: var(--bg-secondary, #1D2D3E) !important;\r\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\r\n color: var(--text, #c5dde8) !important;\r\n }\r\n \r\n .overtype-stats .overtype-stat {\r\n display: flex !important;\r\n align-items: center !important;\r\n gap: 5px !important;\r\n white-space: nowrap !important;\r\n }\r\n \r\n .overtype-stats .live-dot {\r\n width: 8px !important;\r\n height: 8px !important;\r\n background: #4caf50 !important;\r\n border-radius: 50% !important;\r\n animation: overtype-pulse 2s infinite !important;\r\n }\r\n \r\n @keyframes overtype-pulse {\r\n 0%, 100% { opacity: 1; transform: scale(1); }\r\n 50% { opacity: 0.6; transform: scale(1.2); }\r\n }\r\n \r\n\r\n /* Toolbar Styles */\r\n .overtype-toolbar {\r\n display: flex !important;\r\n align-items: center !important;\r\n gap: 4px !important;\r\n padding: 8px !important; /* Override reset */\r\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\r\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\r\n overflow-x: auto !important; /* Allow horizontal scrolling */\r\n overflow-y: hidden !important; /* Hide vertical overflow */\r\n -webkit-overflow-scrolling: touch !important;\r\n flex-shrink: 0 !important;\r\n height: auto !important;\r\n position: relative !important; /* Override reset */\r\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\r\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\r\n }\r\n \r\n /* Thin scrollbar styling */\r\n .overtype-toolbar::-webkit-scrollbar {\r\n height: 4px;\r\n }\r\n \r\n .overtype-toolbar::-webkit-scrollbar-track {\r\n background: transparent;\r\n }\r\n \r\n .overtype-toolbar::-webkit-scrollbar-thumb {\r\n background: rgba(0, 0, 0, 0.2);\r\n border-radius: 2px;\r\n }\r\n\r\n .overtype-toolbar-button {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 32px;\r\n height: 32px;\r\n padding: 0;\r\n border: none;\r\n border-radius: 6px;\r\n background: transparent;\r\n color: var(--toolbar-icon, var(--text-secondary, #666));\r\n cursor: pointer;\r\n transition: all 0.2s ease;\r\n flex-shrink: 0;\r\n }\r\n\r\n .overtype-toolbar-button svg {\r\n width: 20px;\r\n height: 20px;\r\n fill: currentColor;\r\n }\r\n\r\n .overtype-toolbar-button:hover {\r\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\r\n color: var(--toolbar-icon, var(--text-primary, #333));\r\n }\r\n\r\n .overtype-toolbar-button:active {\r\n transform: scale(0.95);\r\n }\r\n\r\n .overtype-toolbar-button.active {\r\n background: var(--toolbar-active, var(--primary, #007bff));\r\n color: var(--toolbar-icon, var(--text-primary, #333));\r\n }\r\n\r\n .overtype-toolbar-button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .overtype-toolbar-separator {\r\n width: 1px;\r\n height: 24px;\r\n background: var(--border, #e0e0e0);\r\n margin: 0 4px;\r\n flex-shrink: 0;\r\n }\r\n\r\n /* Adjust wrapper when toolbar is present */\r\n /* Mobile toolbar adjustments */\r\n @media (max-width: 640px) {\r\n .overtype-toolbar {\r\n padding: 6px;\r\n gap: 2px;\r\n }\r\n\r\n .overtype-toolbar-button {\r\n width: 36px;\r\n height: 36px;\r\n }\r\n\r\n .overtype-toolbar-separator {\r\n margin: 0 2px;\r\n }\r\n }\r\n \r\n /* Plain mode - hide preview and show textarea text */\r\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\r\n display: none !important;\r\n }\r\n \r\n .overtype-container[data-mode=\"plain\"] .overtype-input {\r\n color: var(--text, #0d3b66) !important;\r\n /* Use system font stack for better plain text readability */\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \r\n \"Helvetica Neue\", Arial, sans-serif !important;\r\n }\r\n \r\n /* Ensure textarea remains transparent in overlay mode */\r\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\r\n color: transparent !important;\r\n }\r\n\r\n /* Dropdown menu styles */\r\n .overtype-toolbar-button {\r\n position: relative !important; /* Override reset - needed for dropdown */\r\n }\r\n\r\n .overtype-toolbar-button.dropdown-active {\r\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\r\n }\r\n\r\n .overtype-dropdown-menu {\r\n position: fixed !important; /* Fixed positioning relative to viewport */\r\n background: var(--bg-secondary, white) !important; /* Override reset */\r\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\r\n border-radius: 6px;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\r\n z-index: 10000; /* Very high z-index to ensure visibility */\r\n min-width: 150px;\r\n padding: 4px 0 !important; /* Override reset */\r\n /* Position will be set via JavaScript based on button position */\r\n }\r\n\r\n .overtype-dropdown-item {\r\n display: flex;\r\n align-items: center;\r\n width: 100%;\r\n padding: 8px 12px;\r\n border: none;\r\n background: none;\r\n text-align: left;\r\n cursor: pointer;\r\n font-size: 14px;\r\n color: var(--text, #333);\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\r\n }\r\n\r\n .overtype-dropdown-item:hover {\r\n background: var(--hover-bg, #f0f0f0);\r\n }\r\n\r\n .overtype-dropdown-item.active {\r\n font-weight: 600;\r\n }\r\n\r\n .overtype-dropdown-check {\r\n width: 16px;\r\n margin-right: 8px;\r\n color: var(--h1, #007bff);\r\n }\r\n\r\n .overtype-dropdown-icon {\r\n width: 20px;\r\n margin-right: 8px;\r\n text-align: center;\r\n }\r\n\r\n /* Preview mode styles */\r\n .overtype-container[data-mode=\"preview\"] .overtype-input {\r\n display: none !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\r\n pointer-events: auto !important;\r\n user-select: text !important;\r\n cursor: text !important;\r\n }\r\n\r\n /* Hide syntax markers in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\r\n display: none !important;\r\n }\r\n \r\n /* Hide URL part of links in preview mode - extra specificity */\r\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\r\n .overtype-container[data-mode=\"preview\"] .url-part {\r\n display: none !important;\r\n }\r\n \r\n /* Hide all syntax markers inside links too */\r\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\r\n display: none !important;\r\n }\r\n\r\n /* Headers - restore proper sizing in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\r\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\r\n font-weight: 600 !important;\r\n margin: 0 !important;\r\n display: block !important;\r\n color: inherit !important; /* Use parent text color */\r\n line-height: 1 !important; /* Tight line height for headings */\r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \r\n font-size: 2em !important; \r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \r\n font-size: 1.5em !important; \r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \r\n font-size: 1.17em !important; \r\n }\r\n\r\n /* Lists - restore list styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\r\n display: block !important;\r\n list-style: disc !important;\r\n padding-left: 2em !important;\r\n margin: 1em 0 !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\r\n display: block !important;\r\n list-style: decimal !important;\r\n padding-left: 2em !important;\r\n margin: 1em 0 !important;\r\n }\r\n \r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\r\n display: list-item !important;\r\n margin: 0 !important;\r\n padding: 0 !important;\r\n }\r\n\r\n /* Task list checkboxes - only in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\r\n list-style: none !important;\r\n position: relative !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\r\n margin-right: 0.5em !important;\r\n cursor: default !important;\r\n vertical-align: middle !important;\r\n }\r\n\r\n /* Task list in normal mode - keep syntax visible */\r\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\r\n list-style: none !important;\r\n }\r\n\r\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\r\n color: var(--syntax, #999999) !important;\r\n font-weight: normal !important;\r\n }\r\n\r\n /* Links - make clickable in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\r\n pointer-events: auto !important;\r\n cursor: pointer !important;\r\n color: var(--link, #0066cc) !important;\r\n text-decoration: underline !important;\r\n }\r\n\r\n /* Code blocks - proper pre/code styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\r\n background: #2d2d2d !important;\r\n color: #f8f8f2 !important;\r\n padding: 1.2em !important;\r\n border-radius: 3px !important;\r\n overflow-x: auto !important;\r\n margin: 0 !important;\r\n display: block !important;\r\n }\r\n \r\n /* Cave theme code block background in preview mode */\r\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\r\n background: #11171F !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\r\n background: transparent !important;\r\n color: inherit !important;\r\n padding: 0 !important;\r\n font-family: ${fontFamily} !important;\r\n font-size: 0.9em !important;\r\n line-height: 1.4 !important;\r\n }\r\n\r\n /* Hide old code block lines and fences in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\r\n display: none !important;\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\r\n display: none !important;\r\n }\r\n\r\n /* Blockquotes - enhanced styling in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\r\n display: block !important;\r\n border-left: 4px solid var(--blockquote, #ddd) !important;\r\n padding-left: 1em !important;\r\n margin: 1em 0 !important;\r\n font-style: italic !important;\r\n }\r\n\r\n /* Typography improvements in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\r\n font-family: Georgia, 'Times New Roman', serif !important;\r\n font-size: 16px !important;\r\n line-height: 1.8 !important;\r\n color: var(--text, #333) !important; /* Consistent text color */\r\n }\r\n\r\n /* Inline code in preview mode - keep monospace */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\r\n font-family: ${fontFamily} !important;\r\n font-size: 0.9em !important;\r\n background: rgba(135, 131, 120, 0.15) !important;\r\n padding: 0.2em 0.4em !important;\r\n border-radius: 3px !important;\r\n }\r\n\r\n /* Strong and em elements in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\r\n font-weight: 700 !important;\r\n color: inherit !important; /* Use parent text color */\r\n }\r\n\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\r\n font-style: italic !important;\r\n color: inherit !important; /* Use parent text color */\r\n }\r\n\r\n /* HR in preview mode */\r\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\r\n display: block !important;\r\n border-top: 2px solid var(--hr, #ddd) !important;\r\n text-indent: -9999px !important;\r\n height: 2px !important;\r\n }\r\n\r\n /* Link Tooltip - Base styles (all browsers) */\r\n .overtype-link-tooltip {\r\n /* Visual styles that work for both positioning methods */\r\n background: #333 !important;\r\n color: white !important;\r\n padding: 6px 10px !important;\r\n border-radius: 16px !important;\r\n font-size: 12px !important;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\r\n display: none !important;\r\n z-index: 10000 !important;\r\n cursor: pointer !important;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\r\n max-width: 300px !important;\r\n white-space: nowrap !important;\r\n overflow: hidden !important;\r\n text-overflow: ellipsis !important;\r\n\r\n /* Base positioning for Floating UI fallback */\r\n position: absolute;\r\n }\r\n\r\n .overtype-link-tooltip.visible {\r\n display: flex !important;\r\n }\r\n\r\n /* CSS Anchor Positioning (modern browsers only) */\r\n @supports (position-anchor: --x) and (position-area: center) {\r\n .overtype-link-tooltip {\r\n /* Only anchor positioning specific properties */\r\n position-anchor: var(--target-anchor, --link-0);\r\n position-area: block-end center;\r\n margin-top: 8px !important;\r\n position-try: most-width block-end inline-end, flip-inline, block-start center;\r\n position-visibility: anchors-visible;\r\n }\r\n }\r\n\r\n ${mobileStyles}\r\n `;\r\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\r\n * Toolbar component for OverType editor\r\n * Provides markdown formatting buttons with support for custom buttons\r\n */\r\n\r\nimport * as markdownActions from 'markdown-actions';\r\n\r\nexport class Toolbar {\r\n constructor(editor, options = {}) {\r\n this.editor = editor;\r\n this.container = null;\r\n this.buttons = {};\r\n\r\n // Get toolbar buttons array\r\n this.toolbarButtons = options.toolbarButtons || [];\r\n }\r\n\r\n /**\r\n * Create and render toolbar\r\n */\r\n create() {\r\n this.container = document.createElement('div');\r\n this.container.className = 'overtype-toolbar';\r\n this.container.setAttribute('role', 'toolbar');\r\n this.container.setAttribute('aria-label', 'Formatting toolbar');\r\n\r\n // Create buttons from toolbarButtons array\r\n this.toolbarButtons.forEach(buttonConfig => {\r\n if (buttonConfig.name === 'separator') {\r\n const separator = this.createSeparator();\r\n this.container.appendChild(separator);\r\n } else {\r\n const button = this.createButton(buttonConfig);\r\n this.buttons[buttonConfig.name] = button;\r\n this.container.appendChild(button);\r\n }\r\n });\r\n\r\n // Insert toolbar before the wrapper (as sibling, not child)\r\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\r\n }\r\n\r\n /**\r\n * Create a toolbar separator\r\n */\r\n createSeparator() {\r\n const separator = document.createElement('div');\r\n separator.className = 'overtype-toolbar-separator';\r\n separator.setAttribute('role', 'separator');\r\n return separator;\r\n }\r\n\r\n /**\r\n * Create a toolbar button\r\n */\r\n createButton(buttonConfig) {\r\n const button = document.createElement('button');\r\n button.className = 'overtype-toolbar-button';\r\n button.type = 'button';\r\n button.setAttribute('data-button', buttonConfig.name);\r\n button.title = buttonConfig.title || '';\r\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\r\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\r\n\r\n // Special handling for viewMode dropdown\r\n if (buttonConfig.name === 'viewMode') {\r\n button.classList.add('has-dropdown');\r\n button.dataset.dropdown = 'true';\r\n button.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n this.toggleViewModeDropdown(button);\r\n });\r\n return button;\r\n }\r\n\r\n // Standard button click handler - delegate to performAction\r\n button._clickHandler = (e) => {\r\n e.preventDefault();\r\n const actionId = buttonConfig.actionId || buttonConfig.name;\r\n this.editor.performAction(actionId, e);\r\n };\r\n\r\n button.addEventListener('click', button._clickHandler);\r\n return button;\r\n }\r\n\r\n /**\r\n * Handle button action programmatically\r\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\r\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\r\n * @returns {Promise} Whether the action was executed\r\n */\r\n async handleAction(actionIdOrConfig) {\r\n // Old style: buttonConfig object with .action function - execute directly\r\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\r\n this.editor.textarea.focus();\r\n try {\r\n await actionIdOrConfig.action({\r\n editor: this.editor,\r\n getValue: () => this.editor.getValue(),\r\n setValue: (value) => this.editor.setValue(value),\r\n event: null\r\n });\r\n return true;\r\n } catch (error) {\r\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\r\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\r\n detail: { buttonName: actionIdOrConfig.name, error }\r\n }));\r\n return false;\r\n }\r\n }\r\n\r\n // New style: string actionId - delegate to performAction\r\n if (typeof actionIdOrConfig === 'string') {\r\n return this.editor.performAction(actionIdOrConfig, null);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Sanitize SVG to prevent XSS\r\n */\r\n sanitizeSVG(svg) {\r\n if (typeof svg !== 'string') return '';\r\n\r\n // Remove script tags and on* event handlers\r\n const cleaned = svg\r\n .replace(/)<[^<]*)*<\\/script>/gi, '')\r\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\r\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\r\n\r\n return cleaned;\r\n }\r\n\r\n /**\r\n * Toggle view mode dropdown (internal implementation)\r\n * Not exposed to users - viewMode button behavior is fixed\r\n */\r\n toggleViewModeDropdown(button) {\r\n // Close any existing dropdown\r\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\r\n if (existingDropdown) {\r\n existingDropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n return;\r\n }\r\n\r\n button.classList.add('dropdown-active');\r\n\r\n const dropdown = this.createViewModeDropdown(button);\r\n\r\n // Position dropdown relative to button\r\n const rect = button.getBoundingClientRect();\r\n dropdown.style.position = 'absolute';\r\n dropdown.style.top = `${rect.bottom + 5}px`;\r\n dropdown.style.left = `${rect.left}px`;\r\n\r\n document.body.appendChild(dropdown);\r\n\r\n // Click outside to close\r\n this.handleDocumentClick = (e) => {\r\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\r\n dropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n }\r\n };\r\n\r\n setTimeout(() => {\r\n document.addEventListener('click', this.handleDocumentClick);\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Create view mode dropdown menu (internal implementation)\r\n */\r\n createViewModeDropdown(button) {\r\n const dropdown = document.createElement('div');\r\n dropdown.className = 'overtype-dropdown-menu';\r\n\r\n const items = [\r\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\r\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\r\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\r\n ];\r\n\r\n const currentMode = this.editor.container.dataset.mode || 'normal';\r\n\r\n items.forEach(item => {\r\n const menuItem = document.createElement('button');\r\n menuItem.className = 'overtype-dropdown-item';\r\n menuItem.type = 'button';\r\n menuItem.textContent = item.label;\r\n\r\n if (item.id === currentMode) {\r\n menuItem.classList.add('active');\r\n menuItem.setAttribute('aria-current', 'true');\r\n const checkmark = document.createElement('span');\r\n checkmark.className = 'overtype-dropdown-icon';\r\n checkmark.textContent = item.icon;\r\n menuItem.prepend(checkmark);\r\n }\r\n\r\n menuItem.addEventListener('click', (e) => {\r\n e.preventDefault();\r\n\r\n // Handle view mode changes\r\n switch(item.id) {\r\n case 'plain':\r\n this.editor.showPlainTextarea();\r\n break;\r\n case 'preview':\r\n this.editor.showPreviewMode();\r\n break;\r\n case 'normal':\r\n default:\r\n this.editor.showNormalEditMode();\r\n break;\r\n }\r\n\r\n dropdown.remove();\r\n button.classList.remove('dropdown-active');\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n });\r\n\r\n dropdown.appendChild(menuItem);\r\n });\r\n\r\n return dropdown;\r\n }\r\n\r\n /**\r\n * Update active states of toolbar buttons\r\n */\r\n updateButtonStates() {\r\n try {\r\n const activeFormats = markdownActions.getActiveFormats?.(\r\n this.editor.textarea,\r\n this.editor.textarea.selectionStart\r\n ) || [];\r\n\r\n Object.entries(this.buttons).forEach(([name, button]) => {\r\n if (name === 'viewMode') return; // Skip dropdown button\r\n\r\n let isActive = false;\r\n\r\n switch(name) {\r\n case 'bold':\r\n isActive = activeFormats.includes('bold');\r\n break;\r\n case 'italic':\r\n isActive = activeFormats.includes('italic');\r\n break;\r\n case 'code':\r\n isActive = false; // Disabled: unreliable in code blocks\r\n break;\r\n case 'bulletList':\r\n isActive = activeFormats.includes('bullet-list');\r\n break;\r\n case 'orderedList':\r\n isActive = activeFormats.includes('numbered-list');\r\n break;\r\n case 'taskList':\r\n isActive = activeFormats.includes('task-list');\r\n break;\r\n case 'quote':\r\n isActive = activeFormats.includes('quote');\r\n break;\r\n case 'h1':\r\n isActive = activeFormats.includes('header');\r\n break;\r\n case 'h2':\r\n isActive = activeFormats.includes('header-2');\r\n break;\r\n case 'h3':\r\n isActive = activeFormats.includes('header-3');\r\n break;\r\n }\r\n\r\n button.classList.toggle('active', isActive);\r\n button.setAttribute('aria-pressed', isActive.toString());\r\n });\r\n } catch (error) {\r\n // Silently fail if markdown-actions not available\r\n }\r\n }\r\n\r\n /**\r\n * Destroy toolbar and cleanup\r\n */\r\n destroy() {\r\n if (this.container) {\r\n // Clean up event listeners\r\n if (this.handleDocumentClick) {\r\n document.removeEventListener('click', this.handleDocumentClick);\r\n }\r\n\r\n // Clean up button listeners\r\n Object.values(this.buttons).forEach(button => {\r\n if (button._clickHandler) {\r\n button.removeEventListener('click', button._clickHandler);\r\n delete button._clickHandler;\r\n }\r\n });\r\n\r\n // Remove container\r\n this.container.remove();\r\n this.container = null;\r\n this.buttons = {};\r\n }\r\n }\r\n}\r\n", "/**\r\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\r\n * Shows a clickable tooltip when cursor is within a link\r\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\r\n */\r\n\r\nexport class LinkTooltip {\r\n constructor(editor) {\r\n this.editor = editor;\r\n this.tooltip = null;\r\n this.currentLink = null;\r\n this.hideTimeout = null;\r\n this.visibilityChangeHandler = null;\r\n this.useFloatingUI = false;\r\n this.floatingUI = null;\r\n this.isTooltipHovered = false;\r\n\r\n this.init();\r\n }\r\n\r\n async init() {\r\n // Detect CSS anchor positioning support\r\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\r\n CSS.supports('position-area: center');\r\n\r\n // Load Floating UI if needed\r\n if (!supportsAnchorPositioning) {\r\n try {\r\n // Use indirect eval to prevent bundler from processing the import\r\n const importFn = new Function('url', 'return import(url)');\r\n const { computePosition, offset, shift, flip } = await importFn(\r\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\r\n );\r\n this.floatingUI = { computePosition, offset, shift, flip };\r\n this.useFloatingUI = true;\r\n } catch (error) {\r\n // If dynamic import fails, tooltips simply won't show\r\n console.warn('Failed to load Floating UI fallback:', error);\r\n this.floatingUI = null;\r\n this.useFloatingUI = false;\r\n }\r\n }\r\n\r\n // Create tooltip element\r\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\r\n this.createTooltip();\r\n\r\n // Listen for cursor position changes\r\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\r\n this.editor.textarea.addEventListener('keyup', e => {\r\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\r\n this.checkCursorPosition();\r\n }\r\n });\r\n\r\n // Hide tooltip when typing\r\n this.editor.textarea.addEventListener('input', () => this.hide());\r\n\r\n // Reposition or hide tooltip when scrolling\r\n this.editor.textarea.addEventListener('scroll', () => {\r\n if (this.useFloatingUI && this.currentLink) {\r\n // Reposition the tooltip for Floating UI\r\n this.showWithFloatingUI(this.currentLink);\r\n } else {\r\n // Hide for CSS anchor positioning (native browser behavior handles this)\r\n this.hide();\r\n }\r\n });\r\n\r\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\r\n this.editor.textarea.addEventListener('blur', () => {\r\n if (!this.isTooltipHovered) {\r\n this.hide();\r\n }\r\n });\r\n\r\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\r\n this.visibilityChangeHandler = () => {\r\n if (document.hidden) {\r\n this.hide();\r\n }\r\n };\r\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\r\n\r\n // Track hover state to prevent hiding when clicking tooltip\r\n this.tooltip.addEventListener('mouseenter', () => {\r\n this.isTooltipHovered = true;\r\n this.cancelHide();\r\n });\r\n this.tooltip.addEventListener('mouseleave', () => {\r\n this.isTooltipHovered = false;\r\n this.scheduleHide();\r\n });\r\n }\r\n\r\n createTooltip() {\r\n // Create tooltip element\r\n // Styles are now included in the main stylesheet (styles.js)\r\n this.tooltip = document.createElement('div');\r\n this.tooltip.className = 'overtype-link-tooltip';\r\n\r\n // Add link icon and text container\r\n this.tooltip.innerHTML = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n `;\r\n\r\n // Click handler to open link\r\n this.tooltip.addEventListener('click', e => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (this.currentLink) {\r\n window.open(this.currentLink.url, '_blank');\r\n this.hide();\r\n }\r\n });\r\n\r\n // Append tooltip to editor container\r\n this.editor.container.appendChild(this.tooltip);\r\n }\r\n\r\n checkCursorPosition() {\r\n const cursorPos = this.editor.textarea.selectionStart;\r\n const text = this.editor.textarea.value;\r\n\r\n // Find if cursor is within a markdown link\r\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\r\n\r\n if (linkInfo) {\r\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\r\n this.show(linkInfo);\r\n }\r\n } else {\r\n this.scheduleHide();\r\n }\r\n }\r\n\r\n findLinkAtPosition(text, position) {\r\n // Regex to find markdown links: [text](url)\r\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\r\n let match;\r\n let linkIndex = 0;\r\n\r\n while ((match = linkRegex.exec(text)) !== null) {\r\n const start = match.index;\r\n const end = match.index + match[0].length;\r\n\r\n if (position >= start && position <= end) {\r\n return {\r\n text: match[1],\r\n url: match[2],\r\n index: linkIndex,\r\n start: start,\r\n end: end\r\n };\r\n }\r\n linkIndex++;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n show(linkInfo) {\r\n this.currentLink = linkInfo;\r\n this.cancelHide();\r\n\r\n // Update tooltip content\r\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\r\n urlSpan.textContent = linkInfo.url;\r\n\r\n if (this.useFloatingUI) {\r\n this.showWithFloatingUI(linkInfo);\r\n } else {\r\n this.showWithAnchorPositioning(linkInfo);\r\n }\r\n\r\n this.tooltip.classList.add('visible');\r\n }\r\n\r\n showWithAnchorPositioning(linkInfo) {\r\n // Set the CSS variable to point to the correct anchor\r\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\r\n }\r\n\r\n async showWithFloatingUI(linkInfo) {\r\n // Find the element in preview that corresponds to this link\r\n const anchorElement = this.findAnchorElement(linkInfo.index);\r\n\r\n if (!anchorElement) {\r\n return;\r\n }\r\n\r\n // Check if anchor element is visible and in viewport\r\n const rect = anchorElement.getBoundingClientRect();\r\n if (rect.width === 0 || rect.height === 0) {\r\n return;\r\n }\r\n\r\n try {\r\n // Compute position using Floating UI\r\n const { x, y } = await this.floatingUI.computePosition(\r\n anchorElement,\r\n this.tooltip,\r\n {\r\n placement: 'bottom',\r\n middleware: [\r\n this.floatingUI.offset(8),\r\n this.floatingUI.shift({ padding: 8 }),\r\n this.floatingUI.flip()\r\n ]\r\n }\r\n );\r\n\r\n // Apply position\r\n Object.assign(this.tooltip.style, {\r\n left: `${x}px`,\r\n top: `${y}px`,\r\n position: 'absolute'\r\n });\r\n } catch (error) {\r\n // If Floating UI computation fails, don't show tooltip\r\n console.warn('Floating UI positioning failed:', error);\r\n return;\r\n }\r\n }\r\n\r\n findAnchorElement(linkIndex) {\r\n // Find the element with the matching anchor-name style\r\n const preview = this.editor.preview;\r\n // Direct query for the specific link - more efficient than iterating\r\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\r\n }\r\n\r\n hide() {\r\n this.tooltip.classList.remove('visible');\r\n this.currentLink = null;\r\n this.isTooltipHovered = false;\r\n }\r\n\r\n scheduleHide() {\r\n this.cancelHide();\r\n this.hideTimeout = setTimeout(() => this.hide(), 300);\r\n }\r\n\r\n cancelHide() {\r\n if (this.hideTimeout) {\r\n clearTimeout(this.hideTimeout);\r\n this.hideTimeout = null;\r\n }\r\n }\r\n\r\n destroy() {\r\n this.cancelHide();\r\n\r\n // Remove visibility change listener\r\n if (this.visibilityChangeHandler) {\r\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\r\n this.visibilityChangeHandler = null;\r\n }\r\n\r\n if (this.tooltip && this.tooltip.parentNode) {\r\n this.tooltip.parentNode.removeChild(this.tooltip);\r\n }\r\n this.tooltip = null;\r\n this.currentLink = null;\r\n this.floatingUI = null;\r\n this.useFloatingUI = false;\r\n this.isTooltipHovered = false;\r\n }\r\n}\r\n", "/**\r\n * SVG icons for OverType toolbar\r\n * Quill-style icons with inline styles\r\n */\r\n\r\nexport const boldIcon = `\r\n \r\n \r\n`;\r\n\r\nexport const italicIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\nexport const h1Icon = `\r\n \r\n`;\r\n\r\nexport const h2Icon = `\r\n \r\n`;\r\n\r\nexport const h3Icon = `\r\n \r\n`;\r\n\r\nexport const linkIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\nexport const codeIcon = `\r\n \r\n \r\n \r\n`;\r\n\r\n\r\nexport const bulletListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const orderedListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const quoteIcon = `\r\n \r\n \r\n`;\r\n\r\nexport const taskListIcon = `\r\n \r\n \r\n \r\n \r\n \r\n \r\n`;\r\n\r\nexport const eyeIcon = `\r\n \r\n \r\n`;", "/**\r\n * Toolbar button definitions for OverType editor\r\n * Export built-in buttons that can be used in custom toolbar configurations\r\n */\r\n\r\nimport * as icons from './icons.js';\r\nimport * as markdownActions from 'markdown-actions';\r\n\r\n/**\r\n * Built-in toolbar button definitions\r\n * Each button has: name, actionId, icon, title, action\r\n * - name: DOM identifier for the button element\r\n * - actionId: Canonical action identifier used by performAction\r\n * Action signature: ({ editor, getValue, setValue, event }) => void\r\n */\r\nexport const toolbarButtons = {\r\n bold: {\r\n name: 'bold',\r\n actionId: 'toggleBold',\r\n icon: icons.boldIcon,\r\n title: 'Bold (Ctrl+B)',\r\n action: ({ editor }) => {\r\n markdownActions.toggleBold(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n italic: {\r\n name: 'italic',\r\n actionId: 'toggleItalic',\r\n icon: icons.italicIcon,\r\n title: 'Italic (Ctrl+I)',\r\n action: ({ editor }) => {\r\n markdownActions.toggleItalic(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n code: {\r\n name: 'code',\r\n actionId: 'toggleCode',\r\n icon: icons.codeIcon,\r\n title: 'Inline Code',\r\n action: ({ editor }) => {\r\n markdownActions.toggleCode(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n separator: {\r\n name: 'separator'\r\n // No icon, title, or action - special separator element\r\n },\r\n\r\n link: {\r\n name: 'link',\r\n actionId: 'insertLink',\r\n icon: icons.linkIcon,\r\n title: 'Insert Link',\r\n action: ({ editor }) => {\r\n markdownActions.insertLink(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h1: {\r\n name: 'h1',\r\n actionId: 'toggleH1',\r\n icon: icons.h1Icon,\r\n title: 'Heading 1',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH1(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h2: {\r\n name: 'h2',\r\n actionId: 'toggleH2',\r\n icon: icons.h2Icon,\r\n title: 'Heading 2',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH2(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n h3: {\r\n name: 'h3',\r\n actionId: 'toggleH3',\r\n icon: icons.h3Icon,\r\n title: 'Heading 3',\r\n action: ({ editor }) => {\r\n markdownActions.toggleH3(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n bulletList: {\r\n name: 'bulletList',\r\n actionId: 'toggleBulletList',\r\n icon: icons.bulletListIcon,\r\n title: 'Bullet List',\r\n action: ({ editor }) => {\r\n markdownActions.toggleBulletList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n orderedList: {\r\n name: 'orderedList',\r\n actionId: 'toggleNumberedList',\r\n icon: icons.orderedListIcon,\r\n title: 'Numbered List',\r\n action: ({ editor }) => {\r\n markdownActions.toggleNumberedList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n taskList: {\r\n name: 'taskList',\r\n actionId: 'toggleTaskList',\r\n icon: icons.taskListIcon,\r\n title: 'Task List',\r\n action: ({ editor }) => {\r\n if (markdownActions.toggleTaskList) {\r\n markdownActions.toggleTaskList(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n }\r\n },\r\n\r\n quote: {\r\n name: 'quote',\r\n actionId: 'toggleQuote',\r\n icon: icons.quoteIcon,\r\n title: 'Quote',\r\n action: ({ editor }) => {\r\n markdownActions.toggleQuote(editor.textarea);\r\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\r\n }\r\n },\r\n\r\n viewMode: {\r\n name: 'viewMode',\r\n icon: icons.eyeIcon,\r\n title: 'View mode'\r\n // Special: handled internally by Toolbar class as dropdown\r\n // No action property - dropdown behavior is internal\r\n }\r\n};\r\n\r\n/**\r\n * Default toolbar button layout with separators\r\n * This is used when toolbar: true but no toolbarButtons provided\r\n */\r\nexport const defaultToolbarButtons = [\r\n toolbarButtons.bold,\r\n toolbarButtons.italic,\r\n toolbarButtons.code,\r\n toolbarButtons.separator,\r\n toolbarButtons.link,\r\n toolbarButtons.separator,\r\n toolbarButtons.h1,\r\n toolbarButtons.h2,\r\n toolbarButtons.h3,\r\n toolbarButtons.separator,\r\n toolbarButtons.bulletList,\r\n toolbarButtons.orderedList,\r\n toolbarButtons.taskList,\r\n toolbarButtons.separator,\r\n toolbarButtons.quote,\r\n toolbarButtons.separator,\r\n toolbarButtons.viewMode\r\n];\r\n"], + "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static autoThemeMediaQuery = null; // Media query for auto theme switching\n static autoThemeListener = null; // Listener function for auto theme changes\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Clean up existing auto theme listener if any\n      this._cleanupAutoThemeListener();\n\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Handle auto theme\n      if (theme === 'auto') {\n        this._setupAutoThemeListener();\n        // Apply the initial resolved theme\n        const resolvedTheme = resolveAutoTheme('auto');\n        this._applyResolvedTheme(resolvedTheme);\n      } else {\n        // Get theme object for non-auto themes\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n        // Update container theme attribute\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        // Apply CSS variables to container for instance override\n        if (themeObj && themeObj.colors) {\n          const cssVars = themeToCSSVars(themeObj.colors);\n          this.container.style.cssText += cssVars;\n        }\n\n        // Update preview to reflect new theme\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     * @param {string} themeName - Resolved theme name\n     */\n    _applyResolvedTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      \n      // Update container with resolved theme, but keep auto in data-theme for tracking\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      // Apply CSS variables\n      if (themeObj && themeObj.colors) {\n        const cssVars = themeToCSSVars(themeObj.colors);\n        this.container.style.cssText += cssVars;\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAutoThemeListener() {\n      if (!window.matchMedia) return;\n\n      this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n      this.autoThemeListener = (event) => {\n        const resolvedTheme = event.matches ? 'cave' : 'solar';\n        this._applyResolvedTheme(resolvedTheme);\n      };\n\n      // Use addEventListener if available (modern browsers)\n      if (this.autoThemeMediaQuery.addEventListener) {\n        this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener);\n      } else if (this.autoThemeMediaQuery.addListener) {\n        // Fallback for older browsers\n        this.autoThemeMediaQuery.addListener(this.autoThemeListener);\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAutoThemeListener() {\n      if (this.autoThemeMediaQuery && this.autoThemeListener) {\n        if (this.autoThemeMediaQuery.removeEventListener) {\n          this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener);\n        } else if (this.autoThemeMediaQuery.removeListener) {\n          // Fallback for older browsers\n          this.autoThemeMediaQuery.removeListener(this.autoThemeListener);\n        }\n        this.autoThemeMediaQuery = null;\n        this.autoThemeListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAutoThemeListener();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAutoThemeListener();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAutoThemeListener();\n // Apply the initial resolved theme\n const resolvedTheme = resolveAutoTheme('auto');\n OverType._applyGlobalResolvedTheme(resolvedTheme, customColors);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances - update container theme attribute\n document.querySelectorAll('.overtype-container').forEach(container => {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n container.setAttribute('data-theme', themeName);\n }\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n // Set the theme attribute to update the theme name\n if (themeName && typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', themeName);\n }\n // Also call refreshTheme() to handle cases where the theme name stays the same\n // but the theme object's properties have changed\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n */\n static _applyGlobalResolvedTheme(themeName, customColors = null) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all containers with resolved theme, but keep 'auto' for tracking\n document.querySelectorAll('.overtype-container').forEach(container => {\n container.setAttribute('data-theme', 'auto');\n container.setAttribute('data-resolved-theme', themeName);\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', 'auto');\n webComponent.setAttribute('data-resolved-theme', themeName);\n }\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAutoThemeListener() {\n if (!window.matchMedia) return;\n\n OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n OverType.autoThemeListener = (event) => {\n const resolvedTheme = event.matches ? 'cave' : 'solar';\n OverType._applyGlobalResolvedTheme(resolvedTheme);\n };\n\n // Use addEventListener if available (modern browsers)\n if (OverType.autoThemeMediaQuery.addEventListener) {\n OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener);\n } else if (OverType.autoThemeMediaQuery.addListener) {\n // Fallback for older browsers\n OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener);\n }\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAutoThemeListener() {\n if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) {\n if (OverType.autoThemeMediaQuery.removeEventListener) {\n OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener);\n } else if (OverType.autoThemeMediaQuery.removeListener) {\n // Fallback for older browsers\n OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener);\n }\n OverType.autoThemeMediaQuery = null;\n OverType.autoThemeListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') {\n return themeName;\n }\n\n // Check for system dark mode preference\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], "mappings": "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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAAA,EAElB;;;;;;;;;;;;;;;;;;;AC92BO,MAAM,UAAU;IACrB,MAAM;MACJ,QAAQ;MACR,QAAQ;MACR,WAAW;IACb;IACA,QAAQ;MACN,QAAQ;MACR,QAAQ;MACR,WAAW;IACb;IACA,MAAM;MACJ,QAAQ;MACR,QAAQ;MACR,aAAa;MACb,aAAa;IACf;IACA,MAAM;MACJ,QAAQ;MACR,QAAQ;MACR,aAAa;MACb,SAAS;IACX;IACA,YAAY;MACV,QAAQ;MACR,WAAW;MACX,eAAe;IACjB;IACA,cAAc;MACZ,QAAQ;MACR,WAAW;MACX,aAAa;IACf;IACA,OAAO;MACL,QAAQ;MACR,WAAW;MACX,sBAAsB;IACxB;IACA,UAAU;MACR,QAAQ;MACR,WAAW;MACX,sBAAsB;IACxB;IACA,SAAS,EAAE,QAAQ,KAAK;IACxB,SAAS,EAAE,QAAQ,MAAM;IACzB,SAAS,EAAE,QAAQ,OAAO;IAC1B,SAAS,EAAE,QAAQ,QAAQ;IAC3B,SAAS,EAAE,QAAQ,SAAS;IAC5B,SAAS,EAAE,QAAQ,UAAU;EAC/B;AAKO,WAAS,kBAAkB;AAChC,WAAO;MACL,QAAQ;MACR,QAAQ;MACR,aAAa;MACb,aAAa;MACb,WAAW;MACX,aAAa;MACb,aAAa;MACb,SAAS;MACT,sBAAsB;MACtB,aAAa;MACb,eAAe;MACf,WAAW;IACb;EACF;AAKO,WAAS,kBAAkB,QAAQ;AACxC,WAAO,eAAA,eAAA,CAAA,GAAK,gBAAgB,CAAA,GAAM,MAAA;EACpC;AC1EA,MAAI,YAAY;AAcT,WAAS,eAAe;AAC7B,WAAO;EACT;AAEO,WAAS,SAAS,UAAU,SAAS,MAAM;AAEhD,QAAI,CAAC;AAAW;AAEhB,YAAQ,MAAM,aAAM,QAAQ,EAAE;AAC9B,YAAQ,IAAI,OAAO;AACnB,QAAI,MAAM;AACR,cAAQ,IAAI,SAAS,IAAI;IAC3B;AACA,YAAQ,SAAS;EACnB;AAEO,WAAS,eAAe,UAAU,OAAO;AAE9C,QAAI,CAAC;AAAW;AAEhB,UAAM,WAAW,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACpF,YAAQ,MAAM,wBAAiB,KAAK,EAAE;AACtC,YAAQ,IAAI,aAAa,GAAG,SAAS,cAAc,IAAI,SAAS,YAAY,EAAE;AAC9E,YAAQ,IAAI,kBAAkB,KAAK,UAAU,QAAQ,CAAC;AACtD,YAAQ,IAAI,WAAW,SAAS,MAAM;AAGtC,UAAM,SAAS,SAAS,MAAM,MAAM,KAAK,IAAI,GAAG,SAAS,iBAAiB,EAAE,GAAG,SAAS,cAAc;AACtG,UAAM,QAAQ,SAAS,MAAM,MAAM,SAAS,cAAc,KAAK,IAAI,SAAS,MAAM,QAAQ,SAAS,eAAe,EAAE,CAAC;AACrH,YAAQ,IAAI,YAAY,KAAK,UAAU,MAAM,IAAI,gBAAgB,KAAK,UAAU,KAAK,CAAC;AACtF,YAAQ,SAAS;EACnB;AAEO,WAAS,YAAY,QAAQ;AAElC,QAAI,CAAC;AAAW;AAEhB,YAAQ,MAAM,kBAAW;AACzB,YAAQ,IAAI,mBAAmB,KAAK,UAAU,OAAO,IAAI,CAAC;AAC1D,YAAQ,IAAI,kBAAkB,GAAG,OAAO,cAAc,IAAI,OAAO,YAAY,EAAE;AAC/E,YAAQ,SAAS;EACnB;ACtDA,MAAI,gBAAgB;AAUb,WAAS,WAAW,UAAU,EAAE,MAAM,gBAAgB,aAAa,GAAG;AAC3E,UAAMC,aAAY,aAAa;AAE/B,QAAIA,YAAW;AACb,cAAQ,MAAM,sBAAe;AAC7B,cAAQ,IAAI,sBAAsB,GAAG,SAAS,cAAc,IAAI,SAAS,YAAY,EAAE;AACvF,cAAQ,IAAI,mBAAmB,KAAK,UAAU,IAAI,CAAC;AACnD,cAAQ,IAAI,yBAAyB,gBAAgB,KAAK,YAAY;IACxE;AAGA,aAAS,MAAM;AAEf,UAAM,yBAAyB,SAAS;AACxC,UAAM,uBAAuB,SAAS;AACtC,UAAM,SAAS,SAAS,MAAM,MAAM,GAAG,sBAAsB;AAC7D,UAAM,QAAQ,SAAS,MAAM,MAAM,oBAAoB;AAEvD,QAAIA,YAAW;AACb,cAAQ,IAAI,0BAA0B,KAAK,UAAU,OAAO,MAAM,GAAG,CAAC,CAAC;AACvE,cAAQ,IAAI,0BAA0B,KAAK,UAAU,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;AACxE,cAAQ,IAAI,iCAAiC,KAAK,UAAU,SAAS,MAAM,MAAM,wBAAwB,oBAAoB,CAAC,CAAC;IACjI;AAGA,UAAM,gBAAgB,SAAS;AAI/B,UAAM,eAAe,2BAA2B;AAEhD,QAAI,kBAAkB,QAAQ,kBAAkB,MAAM;AACpD,eAAS,kBAAkB;AAC3B,UAAI;AACF,wBAAgB,SAAS,YAAY,cAAc,OAAO,IAAI;AAC9D,YAAIA;AAAW,kBAAQ,IAAI,yBAAyB,eAAe,iBAAiB,KAAK,MAAM,IAAI,EAAE,QAAQ,OAAO;MACtH,SAAS,OAAO;AACd,wBAAgB;AAChB,YAAIA;AAAW,kBAAQ,IAAI,4BAA4B,KAAK;MAC9D;AACA,eAAS,kBAAkB;IAC7B;AAEA,QAAIA,YAAW;AACb,cAAQ,IAAI,yBAAyB,aAAa;AAClD,cAAQ,IAAI,uBAAuB,aAAa;IAClD;AAGA,QAAI,eAAe;AACjB,YAAM,gBAAgB,SAAS,OAAO;AACtC,YAAM,cAAc,SAAS;AAE7B,UAAIA,YAAW;AACb,gBAAQ,IAAI,oBAAoB,cAAc,MAAM;AACpD,gBAAQ,IAAI,kBAAkB,YAAY,MAAM;MAClD;AAEA,UAAI,gBAAgB,eAAe;AACjC,YAAIA,YAAW;AACb,kBAAQ,IAAI,mDAAmD;AAC/D,kBAAQ,IAAI,aAAa,KAAK,UAAU,cAAc,MAAM,GAAG,GAAG,CAAC,CAAC;AACpE,kBAAQ,IAAI,WAAW,KAAK,UAAU,YAAY,MAAM,GAAG,GAAG,CAAC,CAAC;QAClE;MAGF;IACF;AAEA,QAAI,CAAC,eAAe;AAClB,UAAIA;AAAW,gBAAQ,IAAI,wBAAwB;AAEnD,UAAI,SAAS,UAAU,eAAe;AACpC,YAAIA;AAAW,kBAAQ,IAAI,2CAA2C;AACtE,YAAI;AACF,mBAAS,YAAY,kBAAkB;QACzC,SAAS,GAAG;QAEZ;AACA,iBAAS,QAAQ,SAAS,OAAO;AACjC,YAAI;AACF,mBAAS,YAAY,gBAAgB;QACvC,SAAS,GAAG;QAEZ;AACA,iBAAS,cAAc,IAAI,YAAY,SAAS,EAAE,SAAS,MAAM,YAAY,KAAK,CAAC,CAAC;MACtF,OAAO;AACL,YAAIA;AAAW,kBAAQ,IAAI,6DAA6D;MAC1F;IACF;AAEA,QAAIA;AAAW,cAAQ,IAAI,4BAA4B,gBAAgB,YAAY;AACnF,QAAI,kBAAkB,QAAQ,gBAAgB,MAAM;AAClD,eAAS,kBAAkB,gBAAgB,YAAY;IACzD,OAAO;AACL,eAAS,kBAAkB,wBAAwB,SAAS,YAAY;IAC1E;AAEA,QAAIA,YAAW;AACb,cAAQ,IAAI,uBAAuB,SAAS,MAAM,MAAM;AACxD,cAAQ,SAAS;IACnB;EACF;AChHO,WAAS,gBAAgB,QAAQ;AACtC,WAAO,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,SAAS;EAC5C;AAKO,WAAS,mBAAmB,MAAM,GAAG;AAC1C,QAAI,QAAQ;AACZ,WAAO,KAAK,KAAK,KAAK,KAAK,QAAQ,CAAC,KAAK,QAAQ,CAAC,KAAK,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG;AAC7E;IACF;AACA,WAAO;EACT;AAKO,WAAS,iBAAiB,MAAM,GAAG,WAAW;AACnD,QAAI,QAAQ;AACZ,UAAM,aAAa,YAAY,OAAO;AACtC,WAAO,KAAK,KAAK,KAAK,CAAC,KAAK,KAAK,EAAE,MAAM,UAAU,GAAG;AACpD;IACF;AACA,WAAO;EACT;AAKO,WAAS,sBAAsB,UAAU;AAC9C,UAAM,QAAQ,SAAS,MAAM,MAAM,IAAI;AACvC,QAAI,UAAU;AACd,aAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS;AACjD,YAAM,aAAa,MAAM,KAAK,EAAE,SAAS;AACzC,UAAI,SAAS,kBAAkB,WAAW,SAAS,iBAAiB,UAAU,YAAY;AACxF,iBAAS,iBAAiB;MAC5B;AACA,UAAI,SAAS,gBAAgB,WAAW,SAAS,eAAe,UAAU,YAAY;AAEpF,YAAI,UAAU,MAAM,SAAS,GAAG;AAC9B,mBAAS,eAAe,KAAK,IAAI,UAAU,MAAM,KAAK,EAAE,QAAQ,SAAS,MAAM,MAAM;QACvF,OAAO;AACL,mBAAS,eAAe,UAAU,aAAa;QACjD;MACF;AACA,iBAAW;IACb;EACF;AAKO,WAAS,mBAAmB,UAAU,aAAa,aAAa,YAAY,OAAO;AACxF,QAAI,SAAS,mBAAmB,SAAS,cAAc;AACrD,eAAS,iBAAiB,mBAAmB,SAAS,OAAO,SAAS,cAAc;AACpF,eAAS,eAAe,iBAAiB,SAAS,OAAO,SAAS,cAAc,SAAS;IAC3F,OAAO;AACL,YAAM,yBAAyB,SAAS,iBAAiB,YAAY;AACrE,YAAM,uBAAuB,SAAS,eAAe,YAAY;AACjE,YAAM,mBAAmB,SAAS,MAAM,MAAM,wBAAwB,SAAS,cAAc,MAAM;AACnG,YAAM,iBAAiB,SAAS,MAAM,MAAM,SAAS,cAAc,oBAAoB,MAAM;AAC7F,UAAI,oBAAoB,gBAAgB;AACtC,iBAAS,iBAAiB;AAC1B,iBAAS,eAAe;MAC1B;IACF;AACA,WAAO,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;EAC5E;AAKO,WAAS,+BAA+B,UAAU;AACvD,UAAM,kBAAkB,SAAS,MAAM,MAAM,GAAG,SAAS,cAAc;AACvE,UAAM,iBAAiB,SAAS,MAAM,MAAM,SAAS,YAAY;AAEjE,UAAM,eAAe,gBAAgB,MAAM,MAAM;AACjD,UAAM,cAAc,eAAe,MAAM,MAAM;AAC/C,UAAM,0BAA0B,eAAe,aAAa,CAAC,EAAE,SAAS;AACxE,UAAM,yBAAyB,cAAc,YAAY,CAAC,EAAE,SAAS;AAErE,QAAI,mBAAmB;AACvB,QAAI,oBAAoB;AAExB,QAAI,gBAAgB,MAAM,IAAI,KAAK,0BAA0B,GAAG;AAC9D,yBAAmB,KAAK,OAAO,IAAI,uBAAuB;IAC5D;AAEA,QAAI,eAAe,MAAM,IAAI,KAAK,yBAAyB,GAAG;AAC5D,0BAAoB,KAAK,OAAO,IAAI,sBAAsB;IAC5D;AAEA,WAAO,EAAE,kBAAkB,kBAAkB;EAC/C;AA2BO,WAAS,mBAAmB,UAAU,WAAW,UAAU,CAAC,GAAG;AAEpE,UAAM,gBAAgB,SAAS;AAC/B,UAAM,cAAc,SAAS;AAC7B,UAAM,qBAAqB,kBAAkB;AAG7C,UAAM,QAAQ,SAAS;AACvB,QAAI,YAAY;AAGhB,WAAO,YAAY,KAAK,MAAM,YAAY,CAAC,MAAM,MAAM;AACrD;IACF;AAGA,QAAI,oBAAoB;AAEtB,UAAI,UAAU;AAGd,aAAO,UAAU,MAAM,UAAU,MAAM,OAAO,MAAM,MAAM;AACxD;MACF;AAEA,eAAS,iBAAiB;AAC1B,eAAS,eAAe;IAC1B,OAAO;AAEL,4BAAsB,QAAQ;IAChC;AAGA,UAAM,SAAS,UAAU,QAAQ;AAGjC,QAAI,QAAQ,iBAAiB;AAE3B,YAAM,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACxF,YAAM,aAAa,aAAa,WAAW,QAAQ,MAAM;AACzD,YAAM,WAAW,QAAQ,gBAAgB,YAAY,eAAe,aAAa,SAAS;AAC1F,aAAO,iBAAiB,SAAS;AACjC,aAAO,eAAe,SAAS;IACjC,WAAW,QAAQ,QAAQ;AAEzB,YAAM,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACxF,YAAM,aAAa,aAAa,WAAW,QAAQ,MAAM;AAEzD,UAAI,oBAAoB;AAEtB,YAAI,YAAY;AAEd,iBAAO,iBAAiB,KAAK,IAAI,gBAAgB,QAAQ,OAAO,QAAQ,SAAS;AACjF,iBAAO,eAAe,OAAO;QAC/B,OAAO;AAEL,iBAAO,iBAAiB,gBAAgB,QAAQ,OAAO;AACvD,iBAAO,eAAe,OAAO;QAC/B;MACF,OAAO;AAEL,YAAI,YAAY;AAEd,iBAAO,iBAAiB,KAAK,IAAI,gBAAgB,QAAQ,OAAO,QAAQ,SAAS;AACjF,iBAAO,eAAe,KAAK,IAAI,cAAc,QAAQ,OAAO,QAAQ,SAAS;QAC/E,OAAO;AAEL,iBAAO,iBAAiB,gBAAgB,QAAQ,OAAO;AACvD,iBAAO,eAAe,cAAc,QAAQ,OAAO;QACrD;MACF;IACF;AAEA,WAAO;EACT;AC/LO,WAAS,WAAW,UAAU,OAAO;AAC1C,QAAI;AACJ,QAAI;AAEJ,UAAM,EAAE,QAAQ,QAAQ,aAAa,aAAa,aAAa,aAAa,SAAS,sBAAsB,UAAU,IAAI;AACzH,UAAM,yBAAyB,SAAS;AACxC,UAAM,uBAAuB,SAAS;AAEtC,QAAI,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACtF,QAAI,cAAc,gBAAgB,YAAY,KAAK,eAAe,YAAY,SAAS,IAAI,GAAG,WAAW;IAAO;AAChH,QAAI,cAAc,gBAAgB,YAAY,KAAK,eAAe,YAAY,SAAS,IAAI;EAAK,WAAW,KAAK;AAEhH,QAAI,aAAa;AACf,YAAM,kBAAkB,SAAS,MAAM,SAAS,iBAAiB,CAAC;AAClE,UAAI,SAAS,mBAAmB,KAAK,mBAAmB,QAAQ,CAAC,gBAAgB,MAAM,IAAI,GAAG;AAC5F,sBAAc,IAAI,WAAW;MAC/B;IACF;AAEA,mBAAe,mBAAmB,UAAU,aAAa,aAAa,MAAM,SAAS;AACrF,QAAI,iBAAiB,SAAS;AAC9B,QAAI,eAAe,SAAS;AAC5B,UAAM,iBAAiB,eAAe,YAAY,SAAS,KAAK,YAAY,QAAQ,WAAW,IAAI,MAAM,aAAa,SAAS;AAE/H,QAAI,sBAAsB;AACxB,YAAM,MAAM,+BAA+B,QAAQ;AACnD,yBAAmB,IAAI;AACvB,0BAAoB,IAAI;AACxB,oBAAc,mBAAmB;AACjC,qBAAe;IACjB;AAGA,QAAI,aAAa,WAAW,WAAW,KAAK,aAAa,SAAS,WAAW,GAAG;AAC9E,YAAM,kBAAkB,aAAa,MAAM,YAAY,QAAQ,aAAa,SAAS,YAAY,MAAM;AACvG,UAAI,2BAA2B,sBAAsB;AACnD,YAAI,WAAW,yBAAyB,YAAY;AACpD,mBAAW,KAAK,IAAI,UAAU,cAAc;AAC5C,mBAAW,KAAK,IAAI,UAAU,iBAAiB,gBAAgB,MAAM;AACrE,yBAAiB,eAAe;MAClC,OAAO;AACL,uBAAe,iBAAiB,gBAAgB;MAClD;AACA,aAAO,EAAE,MAAM,iBAAiB,gBAAgB,aAAa;IAC/D,WAAW,CAAC,gBAAgB;AAE1B,UAAI,kBAAkB,cAAc,eAAe;AACnD,uBAAiB,yBAAyB,YAAY;AACtD,qBAAe,uBAAuB,YAAY;AAClD,YAAM,kBAAkB,aAAa,MAAM,YAAY;AACvD,UAAI,aAAa,iBAAiB;AAChC,cAAM,oBAAoB,gBAAgB,CAAC,KAAK;AAChD,cAAM,qBAAqB,gBAAgB,CAAC,KAAK;AACjD,0BAAkB,oBAAoB,cAAc,aAAa,KAAK,IAAI,cAAc;AACxF,0BAAkB,kBAAkB;AACpC,wBAAgB,mBAAmB;MACrC;AACA,aAAO,EAAE,MAAM,iBAAiB,gBAAgB,aAAa;IAC/D,WAAW,WAAW,QAAQ,SAAS,KAAK,aAAa,MAAM,OAAO,GAAG;AAEvE,oBAAc,YAAY,QAAQ,aAAa,YAAY;AAC3D,YAAM,kBAAkB,cAAc;AACtC,uBAAiB,eAAe,iBAAiB,YAAY;AAC7D,aAAO,EAAE,MAAM,iBAAiB,gBAAgB,aAAa;IAC/D,OAAO;AAEL,YAAM,kBAAkB,cAAc,eAAe;AACrD,uBAAiB,iBAAiB,YAAY,SAAS,aAAa,SAAS,YAAY,QAAQ,WAAW;AAC5G,qBAAe,iBAAiB,YAAY;AAC5C,aAAO,EAAE,MAAM,iBAAiB,gBAAgB,aAAa;IAC/D;EACF;AAyBO,WAAS,eAAe,UAAU,OAAO;AAC9C,UAAM,EAAE,QAAQ,QAAQ,qBAAqB,IAAI;AACjD,QAAI,OAAO,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AAC9E,QAAI,iBAAiB,SAAS;AAC9B,QAAI,eAAe,SAAS;AAC5B,UAAM,QAAQ,KAAK,MAAM,IAAI;AAG7B,UAAM,YAAY,MAAM,MAAM,CAAA,SAAQ,KAAK,WAAW,MAAM,MAAM,CAAC,UAAU,KAAK,SAAS,MAAM,EAAE;AAEnG,QAAI,WAAW;AAEb,aAAO,MAAM,IAAI,CAAA,SAAQ;AACvB,YAAI,SAAS,KAAK,MAAM,OAAO,MAAM;AACrC,YAAI,QAAQ;AACV,mBAAS,OAAO,MAAM,GAAG,OAAO,SAAS,OAAO,MAAM;QACxD;AACA,eAAO;MACT,CAAC,EAAE,KAAK,IAAI;AACZ,qBAAe,iBAAiB,KAAK;IACvC,OAAO;AAEL,aAAO,MAAM,IAAI,CAAA,SAAQ,SAAS,QAAQ,UAAU,GAAG,EAAE,KAAK,IAAI;AAClE,UAAI,sBAAsB;AACxB,cAAM,EAAE,kBAAkB,kBAAkB,IAAI,+BAA+B,QAAQ;AACvF,0BAAkB,iBAAiB;AACnC,uBAAe,iBAAiB,KAAK;AACrC,eAAO,mBAAmB,OAAO;MACnC;IACF;AAEA,WAAO,EAAE,MAAM,gBAAgB,aAAa;EAC9C;ACjIA,WAAS,qBAAqB,MAAM;AAClC,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,mBAAmB;AACzB,UAAM,wBAAwB,MAAM,MAAM,CAAA,SAAQ,iBAAiB,KAAK,IAAI,CAAC;AAC7E,QAAI,SAAS;AACb,QAAI,uBAAuB;AACzB,eAAS,MAAM,IAAI,CAAA,SAAQ,KAAK,QAAQ,kBAAkB,EAAE,CAAC;IAC/D;AAEA,WAAO;MACL,MAAM,OAAO,KAAK,IAAI;MACtB,WAAW;IACb;EACF;AAKA,WAAS,uBAAuB,MAAM;AACpC,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,sBAAsB;AAC5B,UAAM,0BAA0B,MAAM,MAAM,CAAA,SAAQ,KAAK,WAAW,mBAAmB,CAAC;AACxF,QAAI,SAAS;AACb,QAAI,yBAAyB;AAC3B,eAAS,MAAM,IAAI,CAAA,SAAQ,KAAK,MAAM,oBAAoB,MAAM,CAAC;IACnE;AAEA,WAAO;MACL,MAAM,OAAO,KAAK,IAAI;MACtB,WAAW;IACb;EACF;AAKA,WAAS,WAAW,OAAO,eAAe;AACxC,QAAI,eAAe;AACjB,aAAO;IACT,OAAO;AACL,aAAO,GAAG,QAAQ,CAAC;IACrB;EACF;AAKA,WAAS,uBAAuB,OAAO,cAAc;AACnD,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,MAAM,aAAa;AACrB,mBAAa,qBAAqB,YAAY;AAC9C,+BAAyB,uBAAuB,WAAW,IAAI;AAC/D,qBAAe,uBAAuB;IACxC,OAAO;AACL,mBAAa,uBAAuB,YAAY;AAChD,+BAAyB,qBAAqB,WAAW,IAAI;AAC7D,qBAAe,uBAAuB;IACxC;AAEA,WAAO,CAAC,YAAY,wBAAwB,YAAY;EAC1D;AAKO,WAAS,UAAU,UAAU,OAAO;AACzC,UAAM,qBAAqB,SAAS,mBAAmB,SAAS;AAChE,QAAI,iBAAiB,SAAS;AAC9B,QAAI,eAAe,SAAS;AAG5B,0BAAsB,QAAQ;AAE9B,UAAM,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AAGxF,UAAM,CAAC,YAAY,wBAAwB,YAAY,IAAI,uBAAuB,OAAO,YAAY;AAErG,UAAM,gBAAgB,aAAa,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU;AACnE,aAAO,GAAG,WAAW,OAAO,MAAM,aAAa,CAAC,GAAG,KAAK;IAC1D,CAAC;AAED,UAAM,oBAAoB,cAAc,OAAO,CAAC,eAAe,eAAe,iBAAiB;AAC7F,aAAO,gBAAgB,WAAW,cAAc,MAAM,aAAa,EAAE;IACvE,GAAG,CAAC;AAEJ,UAAM,gCAAgC,cAAc,OAAO,CAAC,eAAe,eAAe,iBAAiB;AACzG,aAAO,gBAAgB,WAAW,cAAc,CAAC,MAAM,aAAa,EAAE;IACxE,GAAG,CAAC;AAGJ,QAAI,WAAW,WAAW;AACxB,UAAI,oBAAoB;AACtB,yBAAiB,KAAK,IAAI,iBAAiB,WAAW,GAAG,MAAM,aAAa,EAAE,QAAQ,CAAC;AACvF,uBAAe;MACjB,OAAO;AACL,yBAAiB,SAAS;AAC1B,uBAAe,SAAS,eAAe;MACzC;AACA,aAAO,EAAE,MAAM,cAAc,gBAAgB,aAAa;IAC5D;AAGA,UAAM,EAAE,kBAAkB,kBAAkB,IAAI,+BAA+B,QAAQ;AACvF,UAAM,OAAO,mBAAmB,cAAc,KAAK,IAAI,IAAI;AAE3D,QAAI,oBAAoB;AACtB,uBAAiB,KAAK,IAAI,iBAAiB,WAAW,GAAG,MAAM,aAAa,EAAE,SAAS,iBAAiB,QAAQ,CAAC;AACjH,qBAAe;IACjB,OAAO;AACL,UAAI,uBAAuB,WAAW;AAEpC,yBAAiB,KAAK,IAAI,SAAS,iBAAiB,iBAAiB,QAAQ,CAAC;AAC9E,uBAAe,SAAS,eAAe,iBAAiB,SAAS,oBAAoB;MACvF,OAAO;AAEL,yBAAiB,KAAK,IAAI,SAAS,iBAAiB,iBAAiB,QAAQ,CAAC;AAC9E,uBAAe,SAAS,eAAe,iBAAiB,SAAS;MACnE;IACF;AAEA,WAAO,EAAE,MAAM,gBAAgB,aAAa;EAC9C;AAKO,WAAS,eAAe,UAAU,OAAO;AAE9C,UAAM,SAAS;MACb;MACA,CAAC,OAAO,UAAU,IAAI,KAAK;MAC3B;;QAEE,iBAAiB,CAAC,YAAY,UAAU,QAAQ,cAAc;AAE5D,gBAAM,cAAc,SAAS,MAAM,MAAM,WAAW,SAAS,YAAY;AACzE,gBAAM,mBAAmB;AACzB,gBAAM,qBAAqB;AAG3B,gBAAM,iBAAiB,iBAAiB,KAAK,WAAW;AACxD,gBAAM,mBAAmB,mBAAmB,KAAK,WAAW;AAC5D,gBAAM,oBAAqB,MAAM,eAAe,kBAAoB,MAAM,iBAAiB;AAE3F,cAAI,aAAa,QAAQ;AAEvB,gBAAI,mBAAmB;AAErB,oBAAM,cAAc,YAAY,MAAM,MAAM,cAAc,mBAAmB,kBAAkB;AAC/F,oBAAM,eAAe,cAAc,YAAY,CAAC,EAAE,SAAS;AAC3D,qBAAO;gBACL,OAAO,KAAK,IAAI,WAAW,cAAc,SAAS;gBAClD,KAAK,KAAK,IAAI,WAAW,cAAc,SAAS;cAClD;YACF,WAAW,kBAAkB,kBAAkB;AAE7C,oBAAM,iBAAiB,YAAY,MAAM,iBAAiB,mBAAmB,kBAAkB;AAC/F,oBAAM,kBAAkB,iBAAiB,eAAe,CAAC,EAAE,SAAS;AACpE,oBAAM,kBAAkB,MAAM,gBAAgB,IAAI;AAClD,oBAAM,aAAa,kBAAkB;AACrC,qBAAO;gBACL,OAAO,WAAW;gBAClB,KAAK,WAAW;cAClB;YACF,OAAO;AAEL,oBAAM,eAAe,MAAM,gBAAgB,IAAI;AAC/C,qBAAO;gBACL,OAAO,WAAW;gBAClB,KAAK,WAAW;cAClB;YACF;UACF,OAAO;AAEL,gBAAI,mBAAmB;AAErB,oBAAM,cAAc,YAAY,MAAM,MAAM,cAAc,mBAAmB,kBAAkB;AAC/F,oBAAM,eAAe,cAAc,YAAY,CAAC,EAAE,SAAS;AAC3D,qBAAO;gBACL,OAAO,KAAK,IAAI,WAAW,cAAc,SAAS;gBAClD,KAAK,KAAK,IAAI,SAAS,cAAc,SAAS;cAChD;YACF,WAAW,kBAAkB,kBAAkB;AAE7C,oBAAM,iBAAiB,YAAY,MAAM,iBAAiB,mBAAmB,kBAAkB;AAC/F,oBAAM,kBAAkB,iBAAiB,eAAe,CAAC,EAAE,SAAS;AACpE,oBAAM,kBAAkB,MAAM,gBAAgB,IAAI;AAClD,oBAAM,aAAa,kBAAkB;AACrC,qBAAO;gBACL,OAAO,WAAW;gBAClB,KAAK,SAAS;cAChB;YACF,OAAO;AAEL,oBAAM,eAAe,MAAM,gBAAgB,IAAI;AAC/C,qBAAO;gBACL,OAAO,WAAW;gBAClB,KAAK,SAAS;cAChB;YACF;UACF;QACF;MACF;IACF;AAEA,eAAW,UAAU,MAAM;EAC7B;ACtMO,WAAS,iBAAiB,UAAU;AACzC,QAAI,CAAC;AAAU,aAAO,CAAC;AAEvB,UAAM,UAAU,CAAC;AACjB,UAAM,EAAE,gBAAgB,cAAc,MAAM,IAAI;AAGhD,UAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,QAAI,YAAY;AAChB,QAAI,cAAc;AAElB,eAAW,QAAQ,OAAO;AACxB,UAAI,kBAAkB,aAAa,kBAAkB,YAAY,KAAK,QAAQ;AAC5E,sBAAc;AACd;MACF;AACA,mBAAa,KAAK,SAAS;IAC7B;AAGA,QAAI,YAAY,WAAW,IAAI,GAAG;AAChC,UAAI,YAAY,WAAW,QAAQ,KAAK,YAAY,WAAW,QAAQ,GAAG;AACxE,gBAAQ,KAAK,WAAW;MAC1B,OAAO;AACL,gBAAQ,KAAK,aAAa;MAC5B;IACF;AAEA,QAAI,WAAW,KAAK,WAAW,GAAG;AAChC,cAAQ,KAAK,eAAe;IAC9B;AAEA,QAAI,YAAY,WAAW,IAAI,GAAG;AAChC,cAAQ,KAAK,OAAO;IACtB;AAEA,QAAI,YAAY,WAAW,IAAI;AAAG,cAAQ,KAAK,QAAQ;AACvD,QAAI,YAAY,WAAW,KAAK;AAAG,cAAQ,KAAK,UAAU;AAC1D,QAAI,YAAY,WAAW,MAAM;AAAG,cAAQ,KAAK,UAAU;AAG3D,UAAM,aAAa,KAAK,IAAI,GAAG,iBAAiB,EAAE;AAClD,UAAM,YAAY,KAAK,IAAI,MAAM,QAAQ,eAAe,EAAE;AAC1D,UAAM,cAAc,MAAM,MAAM,YAAY,SAAS;AAGrD,QAAI,YAAY,SAAS,IAAI,GAAG;AAC9B,YAAM,eAAe,MAAM,MAAM,KAAK,IAAI,GAAG,iBAAiB,GAAG,GAAG,cAAc;AAClF,YAAM,cAAc,MAAM,MAAM,cAAc,KAAK,IAAI,MAAM,QAAQ,eAAe,GAAG,CAAC;AACxF,YAAM,eAAe,aAAa,YAAY,IAAI;AAClD,YAAM,gBAAgB,YAAY,QAAQ,IAAI;AAC9C,UAAI,iBAAiB,MAAM,kBAAkB,IAAI;AAC/C,gBAAQ,KAAK,MAAM;MACrB;IACF;AAGA,QAAI,YAAY,SAAS,GAAG,GAAG;AAC7B,YAAM,eAAe,MAAM,MAAM,KAAK,IAAI,GAAG,iBAAiB,GAAG,GAAG,cAAc;AAClF,YAAM,cAAc,MAAM,MAAM,cAAc,KAAK,IAAI,MAAM,QAAQ,eAAe,GAAG,CAAC;AACxF,YAAM,iBAAiB,aAAa,YAAY,GAAG;AACnD,YAAM,kBAAkB,YAAY,QAAQ,GAAG;AAC/C,UAAI,mBAAmB,MAAM,oBAAoB,IAAI;AACnD,gBAAQ,KAAK,QAAQ;MACvB;IACF;AAGA,QAAI,YAAY,SAAS,GAAG,GAAG;AAC7B,YAAM,eAAe,MAAM,MAAM,KAAK,IAAI,GAAG,iBAAiB,GAAG,GAAG,cAAc;AAClF,YAAM,cAAc,MAAM,MAAM,cAAc,KAAK,IAAI,MAAM,QAAQ,eAAe,GAAG,CAAC;AACxF,UAAI,aAAa,SAAS,GAAG,KAAK,YAAY,SAAS,GAAG,GAAG;AAC3D,gBAAQ,KAAK,MAAM;MACrB;IACF;AAGA,QAAI,YAAY,SAAS,GAAG,KAAK,YAAY,SAAS,GAAG,GAAG;AAC1D,YAAM,eAAe,MAAM,MAAM,KAAK,IAAI,GAAG,iBAAiB,GAAG,GAAG,cAAc;AAClF,YAAM,cAAc,MAAM,MAAM,cAAc,KAAK,IAAI,MAAM,QAAQ,eAAe,GAAG,CAAC;AACxF,YAAM,kBAAkB,aAAa,YAAY,GAAG;AACpD,YAAM,mBAAmB,YAAY,QAAQ,GAAG;AAChD,UAAI,oBAAoB,MAAM,qBAAqB,IAAI;AACrD,cAAM,eAAe,MAAM,MAAM,eAAe,mBAAmB,GAAG,eAAe,mBAAmB,EAAE;AAC1G,YAAI,aAAa,WAAW,GAAG,GAAG;AAChC,kBAAQ,KAAK,MAAM;QACrB;MACF;IACF;AAEA,WAAO;EACT;ACjGO,WAAS,WAAW,UAAU;AACnC,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAEzD,aAAS,cAAc,UAAU;AACjC,mBAAe,UAAU,QAAQ;AAEjC,UAAM,QAAQ,kBAAkB,QAAQ,IAAI;AAC5C,UAAM,SAAS,WAAW,UAAU,KAAK;AAEzC,gBAAY,MAAM;AAElB,eAAW,UAAU,MAAM;AAE3B,mBAAe,UAAU,OAAO;EAClC;AAKO,WAAS,aAAa,UAAU;AACrC,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AACzD,UAAM,QAAQ,kBAAkB,QAAQ,MAAM;AAC9C,UAAM,SAAS,WAAW,UAAU,KAAK;AACzC,eAAW,UAAU,MAAM;EAC7B;AAKO,WAAS,WAAW,UAAU;AACnC,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAGzD,UAAM,QAAQ,kBAAkB,QAAQ,IAAI;AAC5C,UAAM,SAAS,WAAW,UAAU,KAAK;AACzC,eAAW,UAAU,MAAM;EAC7B;AAKO,WAAS,WAAW,UAAU,UAAU,CAAC,GAAG;AACjD,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAEzD,UAAM,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACxF,QAAI,QAAQ,kBAAkB,QAAQ,IAAI;AAG1C,UAAM,QAAQ,gBAAgB,aAAa,MAAM,cAAc;AAE/D,QAAI,SAAS,CAAC,QAAQ,KAAK;AAEzB,YAAM,SAAS,KAAK,YAAY;AAChC,YAAM,cAAc;IAEtB,WAAW,QAAQ,KAAK;AAEtB,YAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,YAAM,cAAc;IACtB;AAGA,QAAI,QAAQ,QAAQ,CAAC,cAAc;AAEjC,YAAM,MAAM,SAAS;AACrB,eAAS,QAAQ,SAAS,MAAM,MAAM,GAAG,GAAG,IAAI,QAAQ,OAAO,SAAS,MAAM,MAAM,GAAG;AACvF,eAAS,iBAAiB;AAC1B,eAAS,eAAe,MAAM,QAAQ,KAAK;IAC7C;AAEA,UAAM,SAAS,WAAW,UAAU,KAAK;AACzC,eAAW,UAAU,MAAM;EAC7B;AAKO,WAAS,iBAAiB,UAAU;AACzC,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AACzD,UAAM,QAAQ,kBAAkB,QAAQ,UAAU;AAClD,mBAAe,UAAU,KAAK;EAChC;AAKO,WAAS,mBAAmB,UAAU;AAC3C,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AACzD,UAAM,QAAQ,kBAAkB,QAAQ,YAAY;AACpD,mBAAe,UAAU,KAAK;EAChC;AAMO,WAAS,YAAY,UAAU;AACpC,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAEzD,aAAS,eAAe,UAAU;AAClC,mBAAe,UAAU,SAAS;AAElC,UAAM,QAAQ,kBAAkB,QAAQ,KAAK;AAG7C,UAAM,SAAS;MACb;MACA,CAAC,OAAO,eAAe,IAAI,KAAK;MAChC,EAAE,QAAQ,MAAM,OAAO;IACzB;AAEA,gBAAY,MAAM;AAClB,eAAW,UAAU,MAAM;AAC3B,mBAAe,UAAU,OAAO;EAClC;AAMO,WAAS,eAAe,UAAU;AACvC,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAEzD,UAAM,QAAQ,kBAAkB,QAAQ,QAAQ;AAGhD,UAAM,SAAS;MACb;MACA,CAAC,OAAO,eAAe,IAAI,KAAK;MAChC,EAAE,QAAQ,MAAM,OAAO;IACzB;AAEA,eAAW,UAAU,MAAM;EAC7B;AAKO,WAAS,aAAa,UAAU,QAAQ,GAAG,SAAS,OAAO;AAChE,QAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AACzD,QAAI,QAAQ,KAAK,QAAQ;AAAG,cAAQ;AAEpC,aAAS,gBAAgB,iCAAiC;AAC1D,aAAS,gBAAgB,UAAU,KAAK,aAAa,MAAM,EAAE;AAC7D,aAAS,gBAAgB,mBAAmB,SAAS,cAAc,IAAI,SAAS,YAAY,EAAE;AAE9F,UAAM,YAAY,SAAS,UAAU,IAAI,MAAM,KAAK;AACpD,UAAM,QAAQ,kBAAkB,QAAQ,SAAS,KAAK,QAAQ,OAAO;AACrE,aAAS,gBAAgB,kBAAkB,MAAM,MAAM,GAAG;AAG1D,UAAM,QAAQ,SAAS;AACvB,UAAM,gBAAgB,SAAS;AAC/B,UAAM,cAAc,SAAS;AAG7B,QAAI,YAAY;AAChB,WAAO,YAAY,KAAK,MAAM,YAAY,CAAC,MAAM,MAAM;AACrD;IACF;AACA,QAAI,UAAU;AACd,WAAO,UAAU,MAAM,UAAU,MAAM,OAAO,MAAM,MAAM;AACxD;IACF;AAGA,UAAM,qBAAqB,MAAM,MAAM,WAAW,OAAO;AACzD,aAAS,gBAAgB,2BAA2B,kBAAkB,GAAG;AAEzE,UAAM,sBAAsB,mBAAmB,MAAM,cAAc;AACnE,UAAM,gBAAgB,sBAAsB,oBAAoB,CAAC,EAAE,SAAS;AAC5E,UAAM,uBAAuB,sBAAsB,oBAAoB,CAAC,EAAE,SAAS;AAEnF,aAAS,gBAAgB,wBAAwB;AACjD,aAAS,gBAAgB,cAAc,sBAAsB,IAAI,oBAAoB,CAAC,CAAC,MAAM,MAAM,EAAE;AACrG,aAAS,gBAAgB,uBAAuB,aAAa,EAAE;AAC/D,aAAS,gBAAgB,+BAA+B,oBAAoB,EAAE;AAC9E,aAAS,gBAAgB,qBAAqB,KAAK,EAAE;AAGrD,UAAM,kBAAkB,UAAU,kBAAkB;AACpD,aAAS,gBAAgB,sBAAsB,eAAe,YAAY,MAAM,mBAAmB,aAAa,WAAW,KAAK,GAAG;AAGnI,UAAM,SAAS;MACb;MACA,CAAC,OAAO;AACN,cAAM,cAAc,GAAG,MAAM,MAAM,GAAG,gBAAgB,GAAG,YAAY;AACrE,iBAAS,gBAAgB,uBAAuB,WAAW,GAAG;AAG9D,cAAM,cAAc,YAAY,QAAQ,cAAc,EAAE;AACxD,iBAAS,gBAAgB,kBAAkB,WAAW,GAAG;AAEzD,YAAI;AAEJ,YAAI,iBAAiB;AAEnB,mBAAS,gBAAgB,wCAAwC;AACjE,oBAAU;QACZ,WAAW,gBAAgB,GAAG;AAE5B,mBAAS,gBAAgB,sBAAsB,aAAa,UAAU,KAAK,EAAE;AAC7E,oBAAU,MAAM,SAAS;QAC3B,OAAO;AAEL,mBAAS,gBAAgB,2BAA2B;AACpD,oBAAU,MAAM,SAAS;QAC3B;AAEA,iBAAS,gBAAgB,cAAc,OAAO,GAAG;AAEjD,eAAO;UACL,MAAM;UACN,gBAAgB,GAAG;UACnB,cAAc,GAAG;QACnB;MACF;MACA;QACE,QAAQ,MAAM;;QAEd,iBAAiB,CAAC,YAAY,UAAU,QAAQ,iBAAiB;AAC/D,mBAAS,gBAAgB,sBAAsB;AAC/C,mBAAS,gBAAgB,yBAAyB,UAAU,EAAE;AAC9D,mBAAS,gBAAgB,wBAAwB,eAAe,EAAE;AAClE,mBAAS,gBAAgB,iBAAiB,QAAQ,aAAa,MAAM,EAAE;AACvE,mBAAS,gBAAgB,qBAAqB,YAAY,EAAE;AAE5D,cAAI,iBAAiB;AAEnB,kBAAM,aAAa,KAAK,IAAI,WAAW,sBAAsB,YAAY;AACzE,qBAAS,gBAAgB,sCAAsC,oBAAoB,EAAE;AACrF,mBAAO;cACL,OAAO;cACP,KAAK,aAAa,SAAS,aAAa,KAAK,IAAI,SAAS,sBAAsB,YAAY;YAC9F;UACF,WAAW,uBAAuB,GAAG;AAEnC,kBAAM,aAAa,MAAM,OAAO,SAAS;AACzC,qBAAS,gBAAgB,sCAAsC,UAAU,EAAE;AAC3E,mBAAO;cACL,OAAO,WAAW;cAClB,KAAK,SAAS;YAChB;UACF,OAAO;AAEL,qBAAS,gBAAgB,oCAAoC,MAAM,OAAO,MAAM,EAAE;AAClF,mBAAO;cACL,OAAO,WAAW,MAAM,OAAO;cAC/B,KAAK,SAAS,MAAM,OAAO;YAC7B;UACF;QACF;MACF;IACF;AAEA,aAAS,gBAAgB,uBAAuB,OAAO,IAAI,aAAa,OAAO,cAAc,IAAI,OAAO,YAAY,EAAE;AACtH,aAAS,gBAAgB,+BAA+B;AAExD,eAAW,UAAU,MAAM;EAC7B;AAKO,WAAS,SAAS,UAAU;AACjC,iBAAa,UAAU,GAAG,IAAI;EAChC;AAKO,WAAS,SAAS,UAAU;AACjC,iBAAa,UAAU,GAAG,IAAI;EAChC;AAKO,WAAS,SAAS,UAAU;AACjC,iBAAa,UAAU,GAAG,IAAI;EAChC;AAKO,WAASC,kBAAiB,UAAU;AACzC,WAAO,iBAAU,QAAQ;EAC3B;;;ACzSO,MAAM,UAAN,MAAc;AAAA,IACnB,YAAY,QAAQ,UAAU,CAAC,GAAG;AAChC,WAAK,SAAS;AACd,WAAK,YAAY;AACjB,WAAK,UAAU,CAAC;AAGhB,WAAK,iBAAiB,QAAQ,kBAAkB,CAAC;AAAA,IACnD;AAAA;AAAA;AAAA;AAAA,IAKA,SAAS;AACP,WAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,WAAK,UAAU,YAAY;AAC3B,WAAK,UAAU,aAAa,QAAQ,SAAS;AAC7C,WAAK,UAAU,aAAa,cAAc,oBAAoB;AAG9D,WAAK,eAAe,QAAQ,kBAAgB;AAC1C,YAAI,aAAa,SAAS,aAAa;AACrC,gBAAM,YAAY,KAAK,gBAAgB;AACvC,eAAK,UAAU,YAAY,SAAS;AAAA,QACtC,OAAO;AACL,gBAAM,SAAS,KAAK,aAAa,YAAY;AAC7C,eAAK,QAAQ,aAAa,IAAI,IAAI;AAClC,eAAK,UAAU,YAAY,MAAM;AAAA,QACnC;AAAA,MACF,CAAC;AAGD,WAAK,OAAO,UAAU,aAAa,KAAK,WAAW,KAAK,OAAO,OAAO;AAAA,IACxE;AAAA;AAAA;AAAA;AAAA,IAKA,kBAAkB;AAChB,YAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,gBAAU,YAAY;AACtB,gBAAU,aAAa,QAAQ,WAAW;AAC1C,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,aAAa,cAAc;AACzB,YAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,aAAO,YAAY;AACnB,aAAO,OAAO;AACd,aAAO,aAAa,eAAe,aAAa,IAAI;AACpD,aAAO,QAAQ,aAAa,SAAS;AACrC,aAAO,aAAa,cAAc,aAAa,SAAS,aAAa,IAAI;AACzE,aAAO,YAAY,KAAK,YAAY,aAAa,QAAQ,EAAE;AAG3D,UAAI,aAAa,SAAS,YAAY;AACpC,eAAO,UAAU,IAAI,cAAc;AACnC,eAAO,QAAQ,WAAW;AAC1B,eAAO,iBAAiB,SAAS,CAAC,MAAM;AACtC,YAAE,eAAe;AACjB,eAAK,uBAAuB,MAAM;AAAA,QACpC,CAAC;AACD,eAAO;AAAA,MACT;AAGA,aAAO,gBAAgB,CAAC,MAAM;AAC5B,UAAE,eAAe;AACjB,cAAM,WAAW,aAAa,YAAY,aAAa;AACvD,aAAK,OAAO,cAAc,UAAU,CAAC;AAAA,MACvC;AAEA,aAAO,iBAAiB,SAAS,OAAO,aAAa;AACrD,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,MAAM,aAAa,kBAAkB;AAEnC,UAAI,oBAAoB,OAAO,qBAAqB,YAAY,OAAO,iBAAiB,WAAW,YAAY;AAC7G,aAAK,OAAO,SAAS,MAAM;AAC3B,YAAI;AACF,gBAAM,iBAAiB,OAAO;AAAA,YAC5B,QAAQ,KAAK;AAAA,YACb,UAAU,MAAM,KAAK,OAAO,SAAS;AAAA,YACrC,UAAU,CAAC,UAAU,KAAK,OAAO,SAAS,KAAK;AAAA,YAC/C,OAAO;AAAA,UACT,CAAC;AACD,iBAAO;AAAA,QACT,SAAS,OAAO;AACd,kBAAQ,MAAM,WAAW,iBAAiB,IAAI,YAAY,KAAK;AAC/D,eAAK,OAAO,QAAQ,cAAc,IAAI,YAAY,gBAAgB;AAAA,YAChE,QAAQ,EAAE,YAAY,iBAAiB,MAAM,MAAM;AAAA,UACrD,CAAC,CAAC;AACF,iBAAO;AAAA,QACT;AAAA,MACF;AAGA,UAAI,OAAO,qBAAqB,UAAU;AACxC,eAAO,KAAK,OAAO,cAAc,kBAAkB,IAAI;AAAA,MACzD;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,YAAY,KAAK;AACf,UAAI,OAAO,QAAQ;AAAU,eAAO;AAGpC,YAAM,UAAU,IACb,QAAQ,uDAAuD,EAAE,EACjE,QAAQ,kCAAkC,EAAE,EAC5C,QAAQ,2BAA2B,EAAE;AAExC,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,uBAAuB,QAAQ;AAE7B,YAAM,mBAAmB,SAAS,cAAc,yBAAyB;AACzE,UAAI,kBAAkB;AACpB,yBAAiB,OAAO;AACxB,eAAO,UAAU,OAAO,iBAAiB;AACzC;AAAA,MACF;AAEA,aAAO,UAAU,IAAI,iBAAiB;AAEtC,YAAM,WAAW,KAAK,uBAAuB,MAAM;AAGnD,YAAM,OAAO,OAAO,sBAAsB;AAC1C,eAAS,MAAM,WAAW;AAC1B,eAAS,MAAM,MAAM,GAAG,KAAK,SAAS,CAAC;AACvC,eAAS,MAAM,OAAO,GAAG,KAAK,IAAI;AAElC,eAAS,KAAK,YAAY,QAAQ;AAGlC,WAAK,sBAAsB,CAAC,MAAM;AAChC,YAAI,CAAC,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC,OAAO,SAAS,EAAE,MAAM,GAAG;AAC9D,mBAAS,OAAO;AAChB,iBAAO,UAAU,OAAO,iBAAiB;AACzC,mBAAS,oBAAoB,SAAS,KAAK,mBAAmB;AAAA,QAChE;AAAA,MACF;AAEA,iBAAW,MAAM;AACf,iBAAS,iBAAiB,SAAS,KAAK,mBAAmB;AAAA,MAC7D,GAAG,CAAC;AAAA,IACN;AAAA;AAAA;AAAA;AAAA,IAKA,uBAAuB,QAAQ;AAC7B,YAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,eAAS,YAAY;AAErB,YAAM,QAAQ;AAAA,QACZ,EAAE,IAAI,UAAU,OAAO,eAAe,MAAM,SAAI;AAAA,QAChD,EAAE,IAAI,SAAS,OAAO,kBAAkB,MAAM,SAAI;AAAA,QAClD,EAAE,IAAI,WAAW,OAAO,gBAAgB,MAAM,SAAI;AAAA,MACpD;AAEA,YAAM,cAAc,KAAK,OAAO,UAAU,QAAQ,QAAQ;AAE1D,YAAM,QAAQ,UAAQ;AACpB,cAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,iBAAS,YAAY;AACrB,iBAAS,OAAO;AAChB,iBAAS,cAAc,KAAK;AAE5B,YAAI,KAAK,OAAO,aAAa;AAC3B,mBAAS,UAAU,IAAI,QAAQ;AAC/B,mBAAS,aAAa,gBAAgB,MAAM;AAC5C,gBAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,oBAAU,YAAY;AACtB,oBAAU,cAAc,KAAK;AAC7B,mBAAS,QAAQ,SAAS;AAAA,QAC5B;AAEA,iBAAS,iBAAiB,SAAS,CAAC,MAAM;AACxC,YAAE,eAAe;AAGjB,kBAAO,KAAK,IAAI;AAAA,YACd,KAAK;AACH,mBAAK,OAAO,kBAAkB;AAC9B;AAAA,YACF,KAAK;AACH,mBAAK,OAAO,gBAAgB;AAC5B;AAAA,YACF,KAAK;AAAA,YACL;AACE,mBAAK,OAAO,mBAAmB;AAC/B;AAAA,UACJ;AAEA,mBAAS,OAAO;AAChB,iBAAO,UAAU,OAAO,iBAAiB;AACzC,mBAAS,oBAAoB,SAAS,KAAK,mBAAmB;AAAA,QAChE,CAAC;AAED,iBAAS,YAAY,QAAQ;AAAA,MAC/B,CAAC;AAED,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,qBAAqB;AA5OvB;AA6OI,UAAI;AACF,cAAM,kBAAgB,KAAgB,sBAAhB;AAAA,UACpB,KAAK,OAAO;AAAA,UACZ,KAAK,OAAO,SAAS;AAAA,cAClB,CAAC;AAEN,eAAO,QAAQ,KAAK,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM,MAAM,MAAM;AACvD,cAAI,SAAS;AAAY;AAEzB,cAAI,WAAW;AAEf,kBAAO,MAAM;AAAA,YACX,KAAK;AACH,yBAAW,cAAc,SAAS,MAAM;AACxC;AAAA,YACF,KAAK;AACH,yBAAW,cAAc,SAAS,QAAQ;AAC1C;AAAA,YACF,KAAK;AACH,yBAAW;AACX;AAAA,YACF,KAAK;AACH,yBAAW,cAAc,SAAS,aAAa;AAC/C;AAAA,YACF,KAAK;AACH,yBAAW,cAAc,SAAS,eAAe;AACjD;AAAA,YACF,KAAK;AACH,yBAAW,cAAc,SAAS,WAAW;AAC7C;AAAA,YACF,KAAK;AACH,yBAAW,cAAc,SAAS,OAAO;AACzC;AAAA,YACF,KAAK;AACH,yBAAW,cAAc,SAAS,QAAQ;AAC1C;AAAA,YACF,KAAK;AACH,yBAAW,cAAc,SAAS,UAAU;AAC5C;AAAA,YACF,KAAK;AACH,yBAAW,cAAc,SAAS,UAAU;AAC5C;AAAA,UACJ;AAEA,iBAAO,UAAU,OAAO,UAAU,QAAQ;AAC1C,iBAAO,aAAa,gBAAgB,SAAS,SAAS,CAAC;AAAA,QACzD,CAAC;AAAA,MACH,SAAS,OAAO;AAAA,MAEhB;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU;AACR,UAAI,KAAK,WAAW;AAElB,YAAI,KAAK,qBAAqB;AAC5B,mBAAS,oBAAoB,SAAS,KAAK,mBAAmB;AAAA,QAChE;AAGA,eAAO,OAAO,KAAK,OAAO,EAAE,QAAQ,YAAU;AAC5C,cAAI,OAAO,eAAe;AACxB,mBAAO,oBAAoB,SAAS,OAAO,aAAa;AACxD,mBAAO,OAAO;AAAA,UAChB;AAAA,QACF,CAAC;AAGD,aAAK,UAAU,OAAO;AACtB,aAAK,YAAY;AACjB,aAAK,UAAU,CAAC;AAAA,MAClB;AAAA,IACF;AAAA,EACF;;;ACnTO,MAAM,cAAN,MAAkB;AAAA,IACvB,YAAY,QAAQ;AAClB,WAAK,SAAS;AACd,WAAK,UAAU;AACf,WAAK,cAAc;AACnB,WAAK,cAAc;AACnB,WAAK,0BAA0B;AAC/B,WAAK,gBAAgB;AACrB,WAAK,aAAa;AAClB,WAAK,mBAAmB;AAExB,WAAK,KAAK;AAAA,IACZ;AAAA,IAEA,MAAM,OAAO;AAEX,YAAM,4BAA4B,IAAI,SAAS,sBAAsB,KACnC,IAAI,SAAS,uBAAuB;AAGtE,UAAI,CAAC,2BAA2B;AAC9B,YAAI;AAEF,gBAAM,WAAW,IAAI,SAAS,OAAO,oBAAoB;AACzD,gBAAM,EAAE,iBAAiB,QAAQ,OAAO,KAAK,IAAI,MAAM;AAAA,YACrD;AAAA,UACF;AACA,eAAK,aAAa,EAAE,iBAAiB,QAAQ,OAAO,KAAK;AACzD,eAAK,gBAAgB;AAAA,QACvB,SAAS,OAAO;AAEd,kBAAQ,KAAK,wCAAwC,KAAK;AAC1D,eAAK,aAAa;AAClB,eAAK,gBAAgB;AAAA,QACvB;AAAA,MACF;AAIA,WAAK,cAAc;AAGnB,WAAK,OAAO,SAAS,iBAAiB,mBAAmB,MAAM,KAAK,oBAAoB,CAAC;AACzF,WAAK,OAAO,SAAS,iBAAiB,SAAS,OAAK;AAClD,YAAI,EAAE,IAAI,SAAS,OAAO,KAAK,EAAE,QAAQ,UAAU,EAAE,QAAQ,OAAO;AAClE,eAAK,oBAAoB;AAAA,QAC3B;AAAA,MACF,CAAC;AAGD,WAAK,OAAO,SAAS,iBAAiB,SAAS,MAAM,KAAK,KAAK,CAAC;AAGhE,WAAK,OAAO,SAAS,iBAAiB,UAAU,MAAM;AACpD,YAAI,KAAK,iBAAiB,KAAK,aAAa;AAE1C,eAAK,mBAAmB,KAAK,WAAW;AAAA,QAC1C,OAAO;AAEL,eAAK,KAAK;AAAA,QACZ;AAAA,MACF,CAAC;AAGD,WAAK,OAAO,SAAS,iBAAiB,QAAQ,MAAM;AAClD,YAAI,CAAC,KAAK,kBAAkB;AAC1B,eAAK,KAAK;AAAA,QACZ;AAAA,MACF,CAAC;AAGD,WAAK,0BAA0B,MAAM;AACnC,YAAI,SAAS,QAAQ;AACnB,eAAK,KAAK;AAAA,QACZ;AAAA,MACF;AACA,eAAS,iBAAiB,oBAAoB,KAAK,uBAAuB;AAG1E,WAAK,QAAQ,iBAAiB,cAAc,MAAM;AAChD,aAAK,mBAAmB;AACxB,aAAK,WAAW;AAAA,MAClB,CAAC;AACD,WAAK,QAAQ,iBAAiB,cAAc,MAAM;AAChD,aAAK,mBAAmB;AACxB,aAAK,aAAa;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,IAEA,gBAAgB;AAGd,WAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,WAAK,QAAQ,YAAY;AAGzB,WAAK,QAAQ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWzB,WAAK,QAAQ,iBAAiB,SAAS,OAAK;AAC1C,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,YAAI,KAAK,aAAa;AACpB,iBAAO,KAAK,KAAK,YAAY,KAAK,QAAQ;AAC1C,eAAK,KAAK;AAAA,QACZ;AAAA,MACF,CAAC;AAGD,WAAK,OAAO,UAAU,YAAY,KAAK,OAAO;AAAA,IAChD;AAAA,IAEA,sBAAsB;AACpB,YAAM,YAAY,KAAK,OAAO,SAAS;AACvC,YAAM,OAAO,KAAK,OAAO,SAAS;AAGlC,YAAM,WAAW,KAAK,mBAAmB,MAAM,SAAS;AAExD,UAAI,UAAU;AACZ,YAAI,CAAC,KAAK,eAAe,KAAK,YAAY,QAAQ,SAAS,OAAO,KAAK,YAAY,UAAU,SAAS,OAAO;AAC3G,eAAK,KAAK,QAAQ;AAAA,QACpB;AAAA,MACF,OAAO;AACL,aAAK,aAAa;AAAA,MACpB;AAAA,IACF;AAAA,IAEA,mBAAmB,MAAM,UAAU;AAEjC,YAAM,YAAY;AAClB,UAAI;AACJ,UAAI,YAAY;AAEhB,cAAQ,QAAQ,UAAU,KAAK,IAAI,OAAO,MAAM;AAC9C,cAAM,QAAQ,MAAM;AACpB,cAAM,MAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAEnC,YAAI,YAAY,SAAS,YAAY,KAAK;AACxC,iBAAO;AAAA,YACL,MAAM,MAAM,CAAC;AAAA,YACb,KAAK,MAAM,CAAC;AAAA,YACZ,OAAO;AAAA,YACP;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK,UAAU;AACb,WAAK,cAAc;AACnB,WAAK,WAAW;AAGhB,YAAM,UAAU,KAAK,QAAQ,cAAc,4BAA4B;AACvE,cAAQ,cAAc,SAAS;AAE/B,UAAI,KAAK,eAAe;AACtB,aAAK,mBAAmB,QAAQ;AAAA,MAClC,OAAO;AACL,aAAK,0BAA0B,QAAQ;AAAA,MACzC;AAEA,WAAK,QAAQ,UAAU,IAAI,SAAS;AAAA,IACtC;AAAA,IAEA,0BAA0B,UAAU;AAElC,WAAK,QAAQ,MAAM,YAAY,mBAAmB,UAAU,SAAS,KAAK,EAAE;AAAA,IAC9E;AAAA,IAEA,MAAM,mBAAmB,UAAU;AAEjC,YAAM,gBAAgB,KAAK,kBAAkB,SAAS,KAAK;AAE3D,UAAI,CAAC,eAAe;AAClB;AAAA,MACF;AAGA,YAAM,OAAO,cAAc,sBAAsB;AACjD,UAAI,KAAK,UAAU,KAAK,KAAK,WAAW,GAAG;AACzC;AAAA,MACF;AAEA,UAAI;AAEF,cAAM,EAAE,GAAG,EAAE,IAAI,MAAM,KAAK,WAAW;AAAA,UACrC;AAAA,UACA,KAAK;AAAA,UACL;AAAA,YACE,WAAW;AAAA,YACX,YAAY;AAAA,cACV,KAAK,WAAW,OAAO,CAAC;AAAA,cACxB,KAAK,WAAW,MAAM,EAAE,SAAS,EAAE,CAAC;AAAA,cACpC,KAAK,WAAW,KAAK;AAAA,YACvB;AAAA,UACF;AAAA,QACF;AAGA,eAAO,OAAO,KAAK,QAAQ,OAAO;AAAA,UAChC,MAAM,GAAG,CAAC;AAAA,UACV,KAAK,GAAG,CAAC;AAAA,UACT,UAAU;AAAA,QACZ,CAAC;AAAA,MACH,SAAS,OAAO;AAEd,gBAAQ,KAAK,mCAAmC,KAAK;AACrD;AAAA,MACF;AAAA,IACF;AAAA,IAEA,kBAAkB,WAAW;AAE3B,YAAM,UAAU,KAAK,OAAO;AAE5B,aAAO,QAAQ,cAAc,oBAAoB,SAAS,IAAI;AAAA,IAChE;AAAA,IAEA,OAAO;AACL,WAAK,QAAQ,UAAU,OAAO,SAAS;AACvC,WAAK,cAAc;AACnB,WAAK,mBAAmB;AAAA,IAC1B;AAAA,IAEA,eAAe;AACb,WAAK,WAAW;AAChB,WAAK,cAAc,WAAW,MAAM,KAAK,KAAK,GAAG,GAAG;AAAA,IACtD;AAAA,IAEA,aAAa;AACX,UAAI,KAAK,aAAa;AACpB,qBAAa,KAAK,WAAW;AAC7B,aAAK,cAAc;AAAA,MACrB;AAAA,IACF;AAAA,IAEA,UAAU;AACR,WAAK,WAAW;AAGhB,UAAI,KAAK,yBAAyB;AAChC,iBAAS,oBAAoB,oBAAoB,KAAK,uBAAuB;AAC7E,aAAK,0BAA0B;AAAA,MACjC;AAEA,UAAI,KAAK,WAAW,KAAK,QAAQ,YAAY;AAC3C,aAAK,QAAQ,WAAW,YAAY,KAAK,OAAO;AAAA,MAClD;AACA,WAAK,UAAU;AACf,WAAK,cAAc;AACnB,WAAK,aAAa;AAClB,WAAK,gBAAgB;AACrB,WAAK,mBAAmB;AAAA,IAC1B;AAAA,EACF;;;AC7QO,MAAM,WAAW;AAAA;AAAA;AAAA;AAKjB,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAMnB,MAAM,SAAS;AAAA;AAAA;AAIf,MAAM,SAAS;AAAA;AAAA;AAIf,MAAM,SAAS;AAAA;AAAA;AAIf,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAMjB,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAOjB,MAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASvB,MAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUxB,MAAM,YAAY;AAAA;AAAA;AAAA;AAKlB,MAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASrB,MAAM,UAAU;AAAA;AAAA;AAAA;;;AC3DhB,MAAM,iBAAiB;AAAA,IAC5B,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,WAAW,OAAO,QAAQ;AAC1C,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,aAAa,OAAO,QAAQ;AAC5C,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,WAAW,OAAO,QAAQ;AAC1C,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,WAAW;AAAA,MACT,MAAM;AAAA;AAAA,IAER;AAAA,IAEA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,WAAW,OAAO,QAAQ;AAC1C,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,IAAI;AAAA,MACF,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,SAAS,OAAO,QAAQ;AACxC,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,IAAI;AAAA,MACF,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,SAAS,OAAO,QAAQ;AACxC,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,IAAI;AAAA,MACF,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,SAAS,OAAO,QAAQ;AACxC,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,YAAY;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,iBAAiB,OAAO,QAAQ;AAChD,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,aAAa;AAAA,MACX,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,mBAAmB,OAAO,QAAQ;AAClD,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,YAAoB,gBAAgB;AAClC,UAAgB,eAAe,OAAO,QAAQ;AAC9C,iBAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,QACrE;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,QAAgB,YAAY,OAAO,QAAQ;AAC3C,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,IAEA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,MAAY;AAAA,MACZ,OAAO;AAAA;AAAA;AAAA,IAGT;AAAA,EACF;AAMO,MAAM,wBAAwB;AAAA,IACnC,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,IACf,eAAe;AAAA,EACjB;;;AhB5JA,WAAS,gBAAgB,SAAS;AAChC,UAAM,MAAM,CAAC;AACb,KAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,QAAQ;AAC/B,UAAI,CAAC,OAAO,IAAI,SAAS;AAAa;AACtC,YAAM,KAAK,IAAI,YAAY,IAAI;AAC/B,UAAI,IAAI,QAAQ;AACd,YAAI,EAAE,IAAI,IAAI;AAAA,MAChB;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAOA,WAAS,iBAAiB,SAAS;AACjC,UAAM,OAAO,WAAW;AACxB,QAAI,CAAC,MAAM,QAAQ,IAAI;AAAG,aAAO;AACjC,WAAO,KAAK,IAAI,CAAC,SAAS;AAAA,MACxB,OAAM,2BAAK,SAAQ;AAAA,MACnB,WAAU,2BAAK,cAAY,2BAAK,SAAQ;AAAA,MACxC,OAAM,2BAAK,SAAQ;AAAA,MACnB,QAAO,2BAAK,UAAS;AAAA,IACvB,EAAE;AAAA,EACJ;AAQA,WAAS,sBAAsB,aAAa,aAAa;AACvD,UAAM,OAAO,iBAAiB,WAAW;AACzC,UAAM,OAAO,iBAAiB,WAAW;AAEzC,QAAI,SAAS,QAAQ,SAAS;AAAM,aAAO,SAAS;AACpD,QAAI,KAAK,WAAW,KAAK;AAAQ,aAAO;AAExC,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,IAAI,KAAK,CAAC;AAChB,YAAM,IAAI,KAAK,CAAC;AAChB,UAAI,EAAE,SAAS,EAAE,QACb,EAAE,aAAa,EAAE,YACjB,EAAE,SAAS,EAAE,QACb,EAAE,UAAU,EAAE,OAAO;AACvB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAKA,MAAM,YAAN,MAAM,UAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAeX,YAAY,QAAQ,UAAU,CAAC,GAAG;AAEhC,UAAI;AAEJ,UAAI,OAAO,WAAW,UAAU;AAC9B,mBAAW,SAAS,iBAAiB,MAAM;AAC3C,YAAI,SAAS,WAAW,GAAG;AACzB,gBAAM,IAAI,MAAM,mCAAmC,MAAM,EAAE;AAAA,QAC7D;AACA,mBAAW,MAAM,KAAK,QAAQ;AAAA,MAChC,WAAW,kBAAkB,SAAS;AACpC,mBAAW,CAAC,MAAM;AAAA,MACpB,WAAW,kBAAkB,UAAU;AACrC,mBAAW,MAAM,KAAK,MAAM;AAAA,MAC9B,WAAW,MAAM,QAAQ,MAAM,GAAG;AAChC,mBAAW;AAAA,MACb,OAAO;AACL,cAAM,IAAI,MAAM,sEAAsE;AAAA,MACxF;AAGA,YAAM,YAAY,SAAS,IAAI,aAAW;AAExC,YAAI,QAAQ,kBAAkB;AAE5B,kBAAQ,iBAAiB,OAAO,OAAO;AACvC,iBAAO,QAAQ;AAAA,QACjB;AAGA,cAAM,WAAW,OAAO,OAAO,UAAS,SAAS;AACjD,iBAAS,MAAM,SAAS,OAAO;AAC/B,gBAAQ,mBAAmB;AAC3B,kBAAS,UAAU,IAAI,SAAS,QAAQ;AACxC,eAAO;AAAA,MACT,CAAC;AAED,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,MAAM,SAAS,UAAU,CAAC,GAAG;AAC3B,WAAK,UAAU;AAGf,WAAK,gBAAgB,QAAQ,SAAS;AAGtC,WAAK,sBAAsB;AAC3B,WAAK,oBAAoB;AAEzB,WAAK,UAAU,KAAK,cAAc,OAAO;AACzC,WAAK,aAAa,EAAE,UAAS;AAC7B,WAAK,cAAc;AAGnB,gBAAS,aAAa;AAGtB,gBAAS,oBAAoB;AAG7B,YAAM,YAAY,QAAQ,cAAc,qBAAqB;AAC7D,YAAM,UAAU,QAAQ,cAAc,mBAAmB;AACzD,UAAI,aAAa,SAAS;AACxB,aAAK,gBAAgB,WAAW,OAAO;AAAA,MACzC,OAAO;AACL,aAAK,kBAAkB;AAAA,MACzB;AAGA,UAAI,KAAK,eAAe;AACtB,aAAK,SAAS,KAAK,aAAa;AAAA,MAClC;AAGA,WAAK,YAAY,IAAI,iBAAiB,IAAI;AAG1C,WAAK,mBAAmB;AAGxB,WAAK,cAAc,IAAI,YAAY,IAAI;AAKvC,4BAAsB,MAAM;AAC1B,8BAAsB,MAAM;AAC1B,eAAK,SAAS,YAAY,KAAK,QAAQ;AACvC,eAAK,SAAS,aAAa,KAAK,QAAQ;AAAA,QAC1C,CAAC;AAAA,MACH,CAAC;AAGD,WAAK,cAAc;AAGnB,UAAI,KAAK,QAAQ,UAAU;AACzB,aAAK,QAAQ,SAAS,KAAK,SAAS,GAAG,IAAI;AAAA,MAC7C;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,cAAc,SAAS;AACrB,YAAM,WAAW;AAAA;AAAA,QAEf,UAAU;AAAA,QACV,YAAY;AAAA;AAAA,QAEZ,YAAY;AAAA,QACZ,SAAS;AAAA;AAAA,QAGT,QAAQ;AAAA,UACN,UAAU;AAAA;AAAA,UACV,SAAS;AAAA,UACT,YAAY;AAAA,QACd;AAAA;AAAA,QAGA,eAAe,CAAC;AAAA;AAAA,QAGhB,WAAW;AAAA,QACX,YAAY;AAAA;AAAA,QACZ,WAAW;AAAA;AAAA,QACX,WAAW;AAAA;AAAA,QACX,aAAa;AAAA,QACb,OAAO;AAAA;AAAA,QAGP,UAAU;AAAA,QACV,WAAW;AAAA;AAAA,QAGX,mBAAmB;AAAA,QACnB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,gBAAgB;AAAA;AAAA,QAChB,gBAAgB;AAAA,QAChB,YAAY;AAAA;AAAA,QACZ,iBAAiB;AAAA;AAAA,MACnB;AAGA,YAAM,EAAE,OAAO,QAAQ,GAAG,aAAa,IAAI;AAE3C,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,gBAAgB,WAAW,SAAS;AAElC,UAAI,aAAa,UAAU,UAAU,SAAS,oBAAoB,GAAG;AACnE,aAAK,YAAY;AACjB,aAAK,UAAU,UAAU,cAAc,mBAAmB;AAAA,MAC5D,WAAW,SAAS;AAElB,aAAK,UAAU;AAEf,aAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,aAAK,UAAU,YAAY;AAE3B,cAAM,aAAa,KAAK,iBAAiB,UAAS,gBAAgB;AAClE,cAAM,YAAY,OAAO,eAAe,WAAW,aAAa,WAAW;AAC3E,YAAI,WAAW;AACb,eAAK,UAAU,aAAa,cAAc,SAAS;AAAA,QACrD;AAGA,YAAI,KAAK,eAAe;AACtB,gBAAM,WAAW,OAAO,KAAK,kBAAkB,WAAW,SAAS,KAAK,aAAa,IAAI,KAAK;AAC9F,cAAI,YAAY,SAAS,QAAQ;AAC/B,kBAAM,UAAU,eAAe,SAAS,MAAM;AAC9C,iBAAK,UAAU,MAAM,WAAW;AAAA,UAClC;AAAA,QACF;AACA,gBAAQ,WAAW,aAAa,KAAK,WAAW,OAAO;AACvD,aAAK,UAAU,YAAY,OAAO;AAAA,MACpC;AAEA,UAAI,CAAC,KAAK,SAAS;AAEjB,YAAI;AAAW,oBAAU,OAAO;AAChC,YAAI;AAAS,kBAAQ,OAAO;AAC5B,aAAK,kBAAkB;AACvB;AAAA,MACF;AAEA,WAAK,WAAW,KAAK,QAAQ,cAAc,iBAAiB;AAC5D,WAAK,UAAU,KAAK,QAAQ,cAAc,mBAAmB;AAE7D,UAAI,CAAC,KAAK,YAAY,CAAC,KAAK,SAAS;AAEnC,aAAK,UAAU,OAAO;AACtB,aAAK,kBAAkB;AACvB;AAAA,MACF;AAGA,WAAK,QAAQ,YAAY;AAGzB,UAAI,KAAK,QAAQ,UAAU;AACzB,aAAK,QAAQ,MAAM,YAAY,wBAAwB,KAAK,QAAQ,QAAQ;AAAA,MAC9E;AACA,UAAI,KAAK,QAAQ,YAAY;AAC3B,aAAK,QAAQ,MAAM,YAAY,0BAA0B,OAAO,KAAK,QAAQ,UAAU,CAAC;AAAA,MAC1F;AACA,UAAI,KAAK,QAAQ,SAAS;AACxB,aAAK,QAAQ,MAAM,YAAY,sBAAsB,KAAK,QAAQ,OAAO;AAAA,MAC3E;AAGA,WAAK,mBAAmB;AAGxB,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,oBAAoB;AAElB,YAAM,UAAU,KAAK,gBAAgB;AAGrC,WAAK,QAAQ,YAAY;AAGzB,WAAK,WAAW;AAGhB,UAAI,WAAW,KAAK,QAAQ,OAAO;AACjC,aAAK,SAAS,WAAW,KAAK,QAAQ,KAAK;AAAA,MAC7C;AAGA,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,kBAAkB;AAEhB,YAAM,WAAW,KAAK,QAAQ,cAAc,iBAAiB;AAC7D,UAAI;AAAU,eAAO,SAAS;AAG9B,aAAO,KAAK,QAAQ,eAAe;AAAA,IACrC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,aAAa;AAEX,WAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,WAAK,UAAU,YAAY;AAG3B,YAAM,aAAa,KAAK,iBAAiB,UAAS,gBAAgB;AAClE,YAAM,YAAY,OAAO,eAAe,WAAW,aAAa,WAAW;AAC3E,UAAI,WAAW;AACb,aAAK,UAAU,aAAa,cAAc,SAAS;AAAA,MACrD;AAGA,UAAI,KAAK,eAAe;AACtB,cAAM,WAAW,OAAO,KAAK,kBAAkB,WAAW,SAAS,KAAK,aAAa,IAAI,KAAK;AAC9F,YAAI,YAAY,SAAS,QAAQ;AAC/B,gBAAM,UAAU,eAAe,SAAS,MAAM;AAC9C,eAAK,UAAU,MAAM,WAAW;AAAA,QAClC;AAAA,MACF;AAGA,WAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,WAAK,QAAQ,YAAY;AAIzB,UAAI,KAAK,QAAQ,UAAU;AACzB,aAAK,QAAQ,MAAM,YAAY,wBAAwB,KAAK,QAAQ,QAAQ;AAAA,MAC9E;AACA,UAAI,KAAK,QAAQ,YAAY;AAC3B,aAAK,QAAQ,MAAM,YAAY,0BAA0B,OAAO,KAAK,QAAQ,UAAU,CAAC;AAAA,MAC1F;AACA,UAAI,KAAK,QAAQ,SAAS;AACxB,aAAK,QAAQ,MAAM,YAAY,sBAAsB,KAAK,QAAQ,OAAO;AAAA,MAC3E;AAEA,WAAK,QAAQ,YAAY;AAGzB,WAAK,WAAW,SAAS,cAAc,UAAU;AACjD,WAAK,SAAS,YAAY;AAC1B,WAAK,SAAS,cAAc,KAAK,QAAQ;AACzC,WAAK,mBAAmB;AAGxB,UAAI,KAAK,QAAQ,eAAe;AAC9B,eAAO,QAAQ,KAAK,QAAQ,aAAa,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACnE,cAAI,QAAQ,eAAe,QAAQ,SAAS;AAC1C,iBAAK,SAAS,aAAa,MAAM;AAAA,UACnC,WAAW,QAAQ,WAAW,OAAO,UAAU,UAAU;AACvD,mBAAO,OAAO,KAAK,SAAS,OAAO,KAAK;AAAA,UAC1C,OAAO;AACL,iBAAK,SAAS,aAAa,KAAK,KAAK;AAAA,UACvC;AAAA,QACF,CAAC;AAAA,MACH;AAGA,WAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,WAAK,QAAQ,YAAY;AACzB,WAAK,QAAQ,aAAa,eAAe,MAAM;AAG/C,WAAK,QAAQ,YAAY,KAAK,QAAQ;AACtC,WAAK,QAAQ,YAAY,KAAK,OAAO;AAKrC,WAAK,UAAU,YAAY,KAAK,OAAO;AAGvC,UAAI,KAAK,QAAQ,WAAW;AAC1B,aAAK,WAAW,SAAS,cAAc,KAAK;AAC5C,aAAK,SAAS,YAAY;AAC1B,aAAK,UAAU,YAAY,KAAK,QAAQ;AACxC,aAAK,aAAa;AAAA,MACpB;AAGA,WAAK,QAAQ,YAAY,KAAK,SAAS;AAGvC,UAAI,KAAK,QAAQ,YAAY;AAC3B,aAAK,iBAAiB;AAAA,MACxB,OAAO;AAEL,aAAK,UAAU,UAAU,OAAO,sBAAsB;AAAA,MACxD;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,qBAAqB;AACnB,WAAK,SAAS,aAAa,gBAAgB,KAAK;AAChD,WAAK,SAAS,aAAa,eAAe,KAAK;AAC/C,WAAK,SAAS,aAAa,kBAAkB,KAAK;AAClD,WAAK,SAAS,aAAa,cAAc,OAAO;AAChD,WAAK,SAAS,aAAa,cAAc,OAAO;AAChD,WAAK,SAAS,aAAa,qBAAqB,OAAO;AACvD,WAAK,SAAS,aAAa,yBAAyB,OAAO;AAAA,IAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,iBAAiB;AAEf,YAAMC,kBAAiB,KAAK,QAAQ,kBAAkB;AAEtD,WAAK,UAAU,IAAI,QAAQ,MAAM,EAAE,gBAAAA,gBAAe,CAAC;AACnD,WAAK,QAAQ,OAAO;AAGpB,WAAK,4BAA4B,MAAM;AACrC,YAAI,KAAK,SAAS;AAChB,eAAK,QAAQ,mBAAmB;AAAA,QAClC;AAAA,MACF;AACA,WAAK,wBAAwB,MAAM;AACjC,YAAI,KAAK,SAAS;AAChB,eAAK,QAAQ,mBAAmB;AAAA,QAClC;AAAA,MACF;AAGA,WAAK,SAAS,iBAAiB,mBAAmB,KAAK,yBAAyB;AAChF,WAAK,SAAS,iBAAiB,SAAS,KAAK,qBAAqB;AAAA,IACpE;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,2BAA2B;AACzB,UAAI,KAAK,2BAA2B;AAClC,aAAK,SAAS,oBAAoB,mBAAmB,KAAK,yBAAyB;AACnF,aAAK,4BAA4B;AAAA,MACnC;AACA,UAAI,KAAK,uBAAuB;AAC9B,aAAK,SAAS,oBAAoB,SAAS,KAAK,qBAAqB;AACrE,aAAK,wBAAwB;AAAA,MAC/B;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,qBAAqB;AAEnB,WAAK,cAAc,gBAAgB,qBAAqB;AAGxD,UAAI,KAAK,QAAQ,gBAAgB;AAC/B,eAAO,OAAO,KAAK,aAAa,gBAAgB,KAAK,QAAQ,cAAc,CAAC;AAAA,MAC9E;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,gBAAgB;AAEd,UAAI,KAAK,QAAQ,WAAW;AAC1B,aAAK,SAAS,MAAM;AAAA,MACtB;AAGA,UAAI,KAAK,QAAQ,YAAY;AAC3B,YAAI,CAAC,KAAK,UAAU,UAAU,SAAS,sBAAsB,GAAG;AAC9D,eAAK,iBAAiB;AAAA,QACxB;AAAA,MACF,OAAO;AAEL,aAAK,UAAU,UAAU,OAAO,sBAAsB;AAAA,MACxD;AAGA,UAAI,KAAK,QAAQ,WAAW,CAAC,KAAK,SAAS;AAEzC,aAAK,eAAe;AAAA,MACtB,WAAW,CAAC,KAAK,QAAQ,WAAW,KAAK,SAAS;AAEhD,aAAK,yBAAyB;AAC9B,aAAK,QAAQ,QAAQ;AACrB,aAAK,UAAU;AAAA,MACjB;AAGA,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA,IAKA,gBAAgB;AACd,YAAM,OAAO,KAAK,SAAS;AAC3B,YAAM,YAAY,KAAK,SAAS;AAChC,YAAM,aAAa,KAAK,gBAAgB,MAAM,SAAS;AAGvD,YAAM,gBAAgB,KAAK,UAAU,QAAQ,SAAS;AAGtD,YAAM,OAAO,eAAe,MAAM,MAAM,YAAY,KAAK,QAAQ,mBAAmB,KAAK,QAAQ,iBAAiB,aAAa;AAC/H,WAAK,QAAQ,YAAY,QAAQ;AAGjC,WAAK,2BAA2B;AAKhC,UAAI,KAAK,QAAQ,aAAa,KAAK,UAAU;AAC3C,aAAK,aAAa;AAAA,MACpB;AAGA,UAAI,KAAK,QAAQ,YAAY,KAAK,aAAa;AAC7C,aAAK,QAAQ,SAAS,MAAM,IAAI;AAAA,MAClC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,6BAA6B;AAE3B,YAAM,aAAa,KAAK,QAAQ,iBAAiB,aAAa;AAG9D,eAAS,IAAI,GAAG,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG;AACjD,cAAM,YAAY,WAAW,CAAC;AAC9B,cAAM,aAAa,WAAW,IAAI,CAAC;AAGnC,cAAM,aAAa,UAAU;AAC7B,cAAM,cAAc,WAAW;AAE/B,YAAI,CAAC,cAAc,CAAC;AAAa;AAGjC,kBAAU,MAAM,UAAU;AAC1B,mBAAW,MAAM,UAAU;AAG3B,mBAAW,UAAU,IAAI,iBAAiB;AAC1C,oBAAY,UAAU,IAAI,iBAAiB;AAAA,MAK7C;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,gBAAgB,MAAM,WAAW;AAC/B,YAAM,QAAQ,KAAK,UAAU,GAAG,SAAS,EAAE,MAAM,IAAI;AACrD,aAAO,MAAM,SAAS;AAAA,IACxB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,YAAY,OAAO;AACjB,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,cAAc,OAAO;AAEnB,UAAI,MAAM,QAAQ,OAAO;AACvB,cAAM,QAAQ,KAAK,SAAS;AAC5B,cAAM,MAAM,KAAK,SAAS;AAC1B,cAAM,QAAQ,KAAK,SAAS;AAG5B,YAAI,MAAM,YAAY,UAAU,KAAK;AACnC;AAAA,QACF;AAEA,cAAM,eAAe;AAGrB,YAAI,UAAU,OAAO,MAAM,UAAU;AAEnC,gBAAM,SAAS,MAAM,UAAU,GAAG,KAAK;AACvC,gBAAM,YAAY,MAAM,UAAU,OAAO,GAAG;AAC5C,gBAAM,QAAQ,MAAM,UAAU,GAAG;AAEjC,gBAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,gBAAM,YAAY,MAAM,IAAI,UAAQ,KAAK,QAAQ,OAAO,EAAE,CAAC,EAAE,KAAK,IAAI;AAGtE,cAAI,SAAS,aAAa;AAExB,iBAAK,SAAS,kBAAkB,OAAO,GAAG;AAC1C,qBAAS,YAAY,cAAc,OAAO,SAAS;AAAA,UACrD,OAAO;AAEL,iBAAK,SAAS,QAAQ,SAAS,YAAY;AAC3C,iBAAK,SAAS,iBAAiB;AAC/B,iBAAK,SAAS,eAAe,QAAQ,UAAU;AAAA,UACjD;AAAA,QACF,WAAW,UAAU,KAAK;AAExB,gBAAM,SAAS,MAAM,UAAU,GAAG,KAAK;AACvC,gBAAM,YAAY,MAAM,UAAU,OAAO,GAAG;AAC5C,gBAAM,QAAQ,MAAM,UAAU,GAAG;AAEjC,gBAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,gBAAM,WAAW,MAAM,IAAI,UAAQ,OAAO,IAAI,EAAE,KAAK,IAAI;AAGzD,cAAI,SAAS,aAAa;AAExB,iBAAK,SAAS,kBAAkB,OAAO,GAAG;AAC1C,qBAAS,YAAY,cAAc,OAAO,QAAQ;AAAA,UACpD,OAAO;AAEL,iBAAK,SAAS,QAAQ,SAAS,WAAW;AAC1C,iBAAK,SAAS,iBAAiB;AAC/B,iBAAK,SAAS,eAAe,QAAQ,SAAS;AAAA,UAChD;AAAA,QACF,OAAO;AAGL,cAAI,SAAS,aAAa;AACxB,qBAAS,YAAY,cAAc,OAAO,IAAI;AAAA,UAChD,OAAO;AAEL,iBAAK,SAAS,QAAQ,MAAM,UAAU,GAAG,KAAK,IAAI,OAAO,MAAM,UAAU,GAAG;AAC5E,iBAAK,SAAS,iBAAiB,KAAK,SAAS,eAAe,QAAQ;AAAA,UACtE;AAAA,QACF;AAGA,aAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AACjE;AAAA,MACF;AAGA,UAAI,MAAM,QAAQ,WAAW,CAAC,MAAM,YAAY,CAAC,MAAM,WAAW,CAAC,MAAM,WAAW,KAAK,QAAQ,YAAY;AAC3G,YAAI,KAAK,4BAA4B,GAAG;AACtC,gBAAM,eAAe;AACrB;AAAA,QACF;AAAA,MACF;AAGA,YAAM,UAAU,KAAK,UAAU,cAAc,KAAK;AAGlD,UAAI,CAAC,WAAW,KAAK,QAAQ,WAAW;AACtC,aAAK,QAAQ,UAAU,OAAO,IAAI;AAAA,MACpC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,8BAA8B;AAC5B,YAAM,WAAW,KAAK;AACtB,YAAM,YAAY,SAAS;AAC3B,YAAM,UAAU,eAAe,eAAe,SAAS,OAAO,SAAS;AAEvE,UAAI,CAAC,WAAW,CAAC,QAAQ;AAAQ,eAAO;AAGxC,UAAI,QAAQ,QAAQ,KAAK,MAAM,MAAM,aAAa,QAAQ,cAAc;AACtE,aAAK,iBAAiB,OAAO;AAC7B,eAAO;AAAA,MACT;AAGA,UAAI,YAAY,QAAQ,gBAAgB,YAAY,QAAQ,SAAS;AACnE,aAAK,cAAc,SAAS,SAAS;AAAA,MACvC,OAAO;AAEL,aAAK,kBAAkB,OAAO;AAAA,MAChC;AAGA,UAAI,QAAQ,aAAa,YAAY;AACnC,aAAK,2BAA2B;AAAA,MAClC;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,iBAAiB,SAAS;AAExB,WAAK,SAAS,kBAAkB,QAAQ,WAAW,QAAQ,YAAY;AACvE,eAAS,YAAY,QAAQ;AAG7B,WAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACnE;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,kBAAkB,SAAS;AACzB,YAAM,UAAU,eAAe,kBAAkB,OAAO;AACxD,eAAS,YAAY,cAAc,OAAO,OAAO,OAAO;AAGxD,WAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACnE;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,cAAc,SAAS,WAAW;AAEhC,YAAM,kBAAkB,QAAQ,QAAQ,UAAU,YAAY,QAAQ,YAAY;AAGlF,WAAK,SAAS,kBAAkB,WAAW,QAAQ,OAAO;AAC1D,eAAS,YAAY,QAAQ;AAG7B,YAAM,UAAU,eAAe,kBAAkB,OAAO;AACxD,eAAS,YAAY,cAAc,OAAO,OAAO,UAAU,eAAe;AAG1E,YAAM,eAAe,KAAK,SAAS,iBAAiB,gBAAgB;AACpE,WAAK,SAAS,kBAAkB,cAAc,YAAY;AAG1D,WAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACnE;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,6BAA6B;AAE3B,UAAI,KAAK,qBAAqB;AAC5B,qBAAa,KAAK,mBAAmB;AAAA,MACvC;AAGA,WAAK,sBAAsB,WAAW,MAAM;AAC1C,aAAK,oBAAoB;AAAA,MAC3B,GAAG,EAAE;AAAA,IACP;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,sBAAsB;AACpB,YAAM,QAAQ,KAAK,SAAS;AAC5B,YAAM,YAAY,KAAK,SAAS;AAEhC,YAAM,WAAW,eAAe,cAAc,KAAK;AAEnD,UAAI,aAAa,OAAO;AAEtB,YAAI,SAAS;AACb,cAAM,WAAW,MAAM,MAAM,IAAI;AACjC,cAAM,WAAW,SAAS,MAAM,IAAI;AACpC,YAAI,YAAY;AAEhB,iBAAS,IAAI,GAAG,IAAI,SAAS,UAAU,YAAY,WAAW,KAAK;AACjE,cAAI,SAAS,CAAC,MAAM,SAAS,CAAC,GAAG;AAC/B,kBAAM,OAAO,SAAS,CAAC,EAAE,SAAS,SAAS,CAAC,EAAE;AAC9C,gBAAI,YAAY,SAAS,CAAC,EAAE,SAAS,WAAW;AAC9C,wBAAU;AAAA,YACZ;AAAA,UACF;AACA,uBAAa,SAAS,CAAC,EAAE,SAAS;AAAA,QACpC;AAGA,aAAK,SAAS,QAAQ;AACtB,cAAM,eAAe,YAAY;AACjC,aAAK,SAAS,kBAAkB,cAAc,YAAY;AAG1D,aAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACnE;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,aAAa,OAAO;AAElB,WAAK,QAAQ,YAAY,KAAK,SAAS;AACvC,WAAK,QAAQ,aAAa,KAAK,SAAS;AAAA,IAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,WAAW;AACT,aAAO,KAAK,SAAS;AAAA,IACvB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,SAAS,OAAO;AACd,WAAK,SAAS,QAAQ;AACtB,WAAK,cAAc;AAGnB,UAAI,KAAK,QAAQ,YAAY;AAC3B,aAAK,kBAAkB;AAAA,MACzB;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,MAAM,cAAc,UAAU,QAAQ,MAAM;AA/4BhD;AAg5BM,YAAM,WAAW,KAAK;AACtB,UAAI,CAAC;AAAU,eAAO;AAEtB,YAAM,UAAS,UAAK,gBAAL,mBAAmB;AAClC,UAAI,CAAC,QAAQ;AACX,gBAAQ,KAAK,6BAA6B,QAAQ,GAAG;AACrD,eAAO;AAAA,MACT;AAEA,eAAS,MAAM;AAEf,UAAI;AACF,cAAM,OAAO;AAAA,UACX,QAAQ;AAAA,UACR,UAAU,MAAM,KAAK,SAAS;AAAA,UAC9B,UAAU,CAAC,UAAU,KAAK,SAAS,KAAK;AAAA,UACxC;AAAA,QACF,CAAC;AAGD,eAAO;AAAA,MACT,SAAS,OAAO;AACd,gBAAQ,MAAM,qBAAqB,QAAQ,YAAY,KAAK;AAC5D,aAAK,QAAQ,cAAc,IAAI,YAAY,gBAAgB;AAAA,UACzD,QAAQ,EAAE,UAAU,MAAM;AAAA,QAC5B,CAAC,CAAC;AACF,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,gBAAgB,UAAU,CAAC,GAAG;AAC5B,YAAM,WAAW,KAAK,SAAS;AAC/B,UAAI,OAAO,eAAe,MAAM,UAAU,IAAI,OAAO,KAAK,QAAQ,eAAe;AAEjF,UAAI,QAAQ,WAAW;AAErB,eAAO,KAAK,QAAQ,iDAAiD,EAAE;AAEvE,eAAO,KAAK,QAAQ,kFAAkF,EAAE;AAExG,eAAO,KAAK,QAAQ,eAAe,EAAE;AAAA,MACvC;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,iBAAiB;AACf,aAAO,KAAK,QAAQ;AAAA,IACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,eAAe;AACb,aAAO,KAAK,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAAA,IACjD;AAAA;AAAA;AAAA;AAAA,IAKA,QAAQ;AACN,WAAK,SAAS,MAAM;AAAA,IACtB;AAAA;AAAA;AAAA;AAAA,IAKA,OAAO;AACL,WAAK,SAAS,KAAK;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,gBAAgB;AACd,aAAO,KAAK;AAAA,IACd;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,UAAU,CAAC,GAAG;AAh/BzB;AAi/BM,YAAM,sBAAqB,UAAK,YAAL,mBAAc;AACzC,WAAK,UAAU,KAAK,cAAc,EAAE,GAAG,KAAK,SAAS,GAAG,QAAQ,CAAC;AACjE,YAAM,sBAAsB,KAAK,WAC/B,KAAK,QAAQ,WACb,sBAAsB,oBAAoB,KAAK,QAAQ,cAAc;AAGvE,WAAK,mBAAmB;AAExB,UAAI,qBAAqB;AACvB,aAAK,yBAAyB;AAC9B,aAAK,QAAQ,QAAQ;AACrB,aAAK,UAAU;AACf,aAAK,eAAe;AAAA,MACtB;AAEA,WAAK,cAAc;AACnB,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,SAAS,OAAO;AAEd,WAAK,0BAA0B;AAG/B,WAAK,gBAAgB;AAGrB,UAAI,UAAU,QAAQ;AACpB,aAAK,wBAAwB;AAE7B,cAAM,gBAAgB,iBAAiB,MAAM;AAC7C,aAAK,oBAAoB,aAAa;AAAA,MACxC,OAAO;AAEL,cAAM,WAAW,OAAO,UAAU,WAAW,SAAS,KAAK,IAAI;AAC/D,cAAM,YAAY,OAAO,aAAa,WAAW,WAAW,SAAS;AAGrE,YAAI,WAAW;AACb,eAAK,UAAU,aAAa,cAAc,SAAS;AAAA,QACrD;AAGA,YAAI,YAAY,SAAS,QAAQ;AAC/B,gBAAM,UAAU,eAAe,SAAS,MAAM;AAC9C,eAAK,UAAU,MAAM,WAAW;AAAA,QAClC;AAGA,aAAK,cAAc;AAAA,MACrB;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,oBAAoB,WAAW;AAC7B,YAAM,WAAW,SAAS,SAAS;AAGnC,WAAK,UAAU,aAAa,cAAc,MAAM;AAChD,WAAK,UAAU,aAAa,uBAAuB,SAAS;AAG5D,UAAI,YAAY,SAAS,QAAQ;AAC/B,cAAM,UAAU,eAAe,SAAS,MAAM;AAC9C,aAAK,UAAU,MAAM,WAAW;AAAA,MAClC;AAGA,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,0BAA0B;AACxB,UAAI,CAAC,OAAO;AAAY;AAExB,WAAK,sBAAsB,OAAO,WAAW,8BAA8B;AAC3E,WAAK,oBAAoB,CAAC,UAAU;AAClC,cAAM,gBAAgB,MAAM,UAAU,SAAS;AAC/C,aAAK,oBAAoB,aAAa;AAAA,MACxC;AAGA,UAAI,KAAK,oBAAoB,kBAAkB;AAC7C,aAAK,oBAAoB,iBAAiB,UAAU,KAAK,iBAAiB;AAAA,MAC5E,WAAW,KAAK,oBAAoB,aAAa;AAE/C,aAAK,oBAAoB,YAAY,KAAK,iBAAiB;AAAA,MAC7D;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,4BAA4B;AAC1B,UAAI,KAAK,uBAAuB,KAAK,mBAAmB;AACtD,YAAI,KAAK,oBAAoB,qBAAqB;AAChD,eAAK,oBAAoB,oBAAoB,UAAU,KAAK,iBAAiB;AAAA,QAC/E,WAAW,KAAK,oBAAoB,gBAAgB;AAElD,eAAK,oBAAoB,eAAe,KAAK,iBAAiB;AAAA,QAChE;AACA,aAAK,sBAAsB;AAC3B,aAAK,oBAAoB;AAAA,MAC3B;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,mBAAmB,aAAa;AAC9B,WAAK,QAAQ,kBAAkB;AAC/B,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,eAAe;AACb,UAAI,CAAC,KAAK;AAAU;AAEpB,YAAM,QAAQ,KAAK,SAAS;AAC5B,YAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,YAAM,QAAQ,MAAM;AACpB,YAAM,QAAQ,MAAM,MAAM,KAAK,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC,EAAE;AAG3D,YAAM,iBAAiB,KAAK,SAAS;AACrC,YAAM,eAAe,MAAM,UAAU,GAAG,cAAc;AACtD,YAAM,oBAAoB,aAAa,MAAM,IAAI;AACjD,YAAM,cAAc,kBAAkB;AACtC,YAAM,gBAAgB,kBAAkB,kBAAkB,SAAS,CAAC,EAAE,SAAS;AAG/E,UAAI,KAAK,QAAQ,gBAAgB;AAC/B,aAAK,SAAS,YAAY,KAAK,QAAQ,eAAe;AAAA,UACpD;AAAA,UACA;AAAA,UACA,OAAO,MAAM;AAAA,UACb,MAAM;AAAA,UACN,QAAQ;AAAA,QACV,CAAC;AAAA,MACH,OAAO;AAEL,aAAK,SAAS,YAAY;AAAA;AAAA;AAAA,oBAGd,KAAK,WAAW,KAAK,WAAW,MAAM,MAAM;AAAA;AAAA,4CAEpB,WAAW,SAAS,aAAa;AAAA;AAAA,MAEvE;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,mBAAmB;AAEjB,WAAK,UAAU,UAAU,IAAI,sBAAsB;AAGnD,WAAK,iBAAiB;AAGtB,WAAK,kBAAkB;AAGvB,WAAK,SAAS,iBAAiB,SAAS,MAAM,KAAK,kBAAkB,CAAC;AAGtE,aAAO,iBAAiB,UAAU,MAAM,KAAK,kBAAkB,CAAC;AAAA,IAClE;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,oBAAoB;AAClB,UAAI,CAAC,KAAK,QAAQ;AAAY;AAE9B,YAAM,WAAW,KAAK;AACtB,YAAM,UAAU,KAAK;AACrB,YAAM,UAAU,KAAK;AAGrB,YAAM,WAAW,OAAO,iBAAiB,QAAQ;AACjD,YAAM,aAAa,WAAW,SAAS,UAAU;AACjD,YAAM,gBAAgB,WAAW,SAAS,aAAa;AAGvD,YAAM,YAAY,SAAS;AAG3B,eAAS,MAAM,YAAY,UAAU,QAAQ,WAAW;AAGxD,UAAI,YAAY,SAAS;AAGzB,UAAI,KAAK,QAAQ,WAAW;AAC1B,cAAM,YAAY,SAAS,KAAK,QAAQ,SAAS;AACjD,oBAAY,KAAK,IAAI,WAAW,SAAS;AAAA,MAC3C;AAGA,UAAI,WAAW;AACf,UAAI,KAAK,QAAQ,WAAW;AAC1B,cAAM,YAAY,SAAS,KAAK,QAAQ,SAAS;AACjD,YAAI,YAAY,WAAW;AACzB,sBAAY;AACZ,qBAAW;AAAA,QACb;AAAA,MACF;AAGA,YAAM,WAAW,YAAY;AAC7B,eAAS,MAAM,YAAY,UAAU,UAAU,WAAW;AAC1D,eAAS,MAAM,YAAY,cAAc,UAAU,WAAW;AAE9D,cAAQ,MAAM,YAAY,UAAU,UAAU,WAAW;AACzD,cAAQ,MAAM,YAAY,cAAc,UAAU,WAAW;AAE7D,cAAQ,MAAM,YAAY,UAAU,UAAU,WAAW;AAGzD,eAAS,YAAY;AACrB,cAAQ,YAAY;AAGpB,UAAI,KAAK,mBAAmB,WAAW;AACrC,aAAK,iBAAiB;AAAA,MAExB;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,UAAU,MAAM;AACd,WAAK,QAAQ,YAAY;AAEzB,UAAI,QAAQ,CAAC,KAAK,UAAU;AAE1B,aAAK,WAAW,SAAS,cAAc,KAAK;AAC5C,aAAK,SAAS,YAAY;AAC1B,aAAK,UAAU,YAAY,KAAK,QAAQ;AACxC,aAAK,aAAa;AAAA,MACpB,WAAW,QAAQ,KAAK,UAAU;AAEhC,aAAK,aAAa;AAAA,MACpB,WAAW,CAAC,QAAQ,KAAK,UAAU;AAEjC,aAAK,SAAS,OAAO;AACrB,aAAK,WAAW;AAAA,MAClB;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,qBAAqB;AACnB,WAAK,UAAU,QAAQ,OAAO;AAC9B,WAAK,cAAc;AAGnB,4BAAsB,MAAM;AAC1B,aAAK,SAAS,YAAY,KAAK,QAAQ;AACvC,aAAK,SAAS,aAAa,KAAK,QAAQ;AAAA,MAC1C,CAAC;AAED,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,oBAAoB;AAClB,WAAK,UAAU,QAAQ,OAAO;AAG9B,UAAI,KAAK,SAAS;AAChB,cAAM,YAAY,KAAK,UAAU,cAAc,8BAA8B;AAC7E,YAAI,WAAW;AACb,oBAAU,UAAU,OAAO,QAAQ;AACnC,oBAAU,QAAQ;AAAA,QACpB;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,kBAAkB;AAChB,WAAK,UAAU,QAAQ,OAAO;AAC9B,WAAK,cAAc;AACnB,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU;AAER,WAAK,0BAA0B;AAG/B,WAAK,QAAQ,mBAAmB;AAChC,gBAAS,UAAU,OAAO,KAAK,OAAO;AAGtC,UAAI,KAAK,WAAW;AAClB,aAAK,UAAU,QAAQ;AAAA,MACzB;AAGA,UAAI,KAAK,SAAS;AAChB,cAAM,UAAU,KAAK,SAAS;AAC9B,aAAK,QAAQ,OAAO;AAGpB,aAAK,QAAQ,cAAc;AAAA,MAC7B;AAEA,WAAK,cAAc;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,OAAO,KAAK,QAAQ,UAAU,CAAC,GAAG;AAChC,aAAO,IAAI,UAAS,QAAQ,OAAO;AAAA,IACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWA,OAAO,aAAa,UAAU,WAAW,CAAC,GAAG;AAC3C,YAAM,WAAW,SAAS,iBAAiB,QAAQ;AACnD,aAAO,MAAM,KAAK,QAAQ,EAAE,IAAI,QAAM;AACpC,cAAM,UAAU,EAAE,GAAG,SAAS;AAG9B,mBAAW,QAAQ,GAAG,YAAY;AAChC,cAAI,KAAK,KAAK,WAAW,UAAU,GAAG;AACpC,kBAAM,QAAQ,KAAK,KAAK,MAAM,CAAC;AAC/B,kBAAM,MAAM,MAAM,QAAQ,aAAa,CAAC,GAAG,MAAM,EAAE,YAAY,CAAC;AAChE,oBAAQ,GAAG,IAAI,UAAS,gBAAgB,KAAK,KAAK;AAAA,UACpD;AAAA,QACF;AAEA,eAAO,IAAI,UAAS,IAAI,OAAO;AAAA,MACjC,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,gBAAgB,OAAO;AAC5B,UAAI,UAAU;AAAQ,eAAO;AAC7B,UAAI,UAAU;AAAS,eAAO;AAC9B,UAAI,UAAU;AAAQ,eAAO;AAC7B,UAAI,UAAU,MAAM,CAAC,MAAM,OAAO,KAAK,CAAC;AAAG,eAAO,OAAO,KAAK;AAC9D,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,YAAY,SAAS;AAC1B,aAAO,QAAQ,oBAAoB,UAAS,UAAU,IAAI,OAAO,KAAK;AAAA,IACxE;AAAA;AAAA;AAAA;AAAA,IAKA,OAAO,aAAa;AAClB,YAAM,WAAW,SAAS,iBAAiB,0BAA0B;AACrE,eAAS,QAAQ,aAAW;AAC1B,cAAM,WAAW,UAAS,YAAY,OAAO;AAC7C,YAAI,UAAU;AACZ,mBAAS,QAAQ;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,aAAa,QAAQ,OAAO;AACjC,UAAI,UAAS,kBAAkB,CAAC;AAAO;AAGvC,YAAM,WAAW,SAAS,cAAc,uBAAuB;AAC/D,UAAI,UAAU;AACZ,iBAAS,OAAO;AAAA,MAClB;AAGA,YAAM,QAAQ,UAAS,gBAAgB;AACvC,YAAM,SAAS,eAAe,EAAE,MAAM,CAAC;AACvC,YAAM,UAAU,SAAS,cAAc,OAAO;AAC9C,cAAQ,YAAY;AACpB,cAAQ,cAAc;AACtB,eAAS,KAAK,YAAY,OAAO;AAEjC,gBAAS,iBAAiB;AAAA,IAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,SAAS,OAAO,eAAe,MAAM;AAE1C,gBAAS,gCAAgC;AAGzC,UAAI,UAAU,QAAQ;AACpB,kBAAS,8BAA8B;AAEvC,cAAM,gBAAgB,iBAAiB,MAAM;AAC7C,kBAAS,0BAA0B,eAAe,YAAY;AAAA,MAChE,OAAO;AAEL,YAAI,WAAW,OAAO,UAAU,WAAW,SAAS,KAAK,IAAI;AAG7D,YAAI,cAAc;AAChB,qBAAW,WAAW,UAAU,YAAY;AAAA,QAC9C;AAGA,kBAAS,eAAe;AAGxB,kBAAS,aAAa,IAAI;AAG1B,iBAAS,iBAAiB,qBAAqB,EAAE,QAAQ,eAAa;AACpE,gBAAMC,aAAY,OAAO,aAAa,WAAW,WAAW,SAAS;AACrE,cAAIA,YAAW;AACb,sBAAU,aAAa,cAAcA,UAAS;AAAA,UAChD;AAAA,QACF,CAAC;AAGD,iBAAS,iBAAiB,mBAAmB,EAAE,QAAQ,aAAW;AAChE,cAAI,CAAC,QAAQ,QAAQ,qBAAqB,GAAG;AAC3C,kBAAMA,aAAY,OAAO,aAAa,WAAW,WAAW,SAAS;AACrE,gBAAIA,YAAW;AACb,sBAAQ,aAAa,cAAcA,UAAS;AAAA,YAC9C;AAAA,UACF;AAGA,gBAAM,WAAW,QAAQ;AACzB,cAAI,UAAU;AACZ,qBAAS,cAAc;AAAA,UACzB;AAAA,QACF,CAAC;AAGD,cAAM,YAAY,OAAO,aAAa,WAAW,WAAW,SAAS;AACrE,iBAAS,iBAAiB,iBAAiB,EAAE,QAAQ,kBAAgB;AAEnE,cAAI,aAAa,OAAO,aAAa,iBAAiB,YAAY;AAChE,yBAAa,aAAa,SAAS,SAAS;AAAA,UAC9C;AAGA,cAAI,OAAO,aAAa,iBAAiB,YAAY;AACnD,yBAAa,aAAa;AAAA,UAC5B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,OAAO,0BAA0B,WAAW,eAAe,MAAM;AAC/D,UAAI,WAAW,SAAS,SAAS;AAGjC,UAAI,cAAc;AAChB,mBAAW,WAAW,UAAU,YAAY;AAAA,MAC9C;AAGA,gBAAS,eAAe;AAGxB,gBAAS,aAAa,IAAI;AAG1B,eAAS,iBAAiB,qBAAqB,EAAE,QAAQ,eAAa;AACpE,kBAAU,aAAa,cAAc,MAAM;AAC3C,kBAAU,aAAa,uBAAuB,SAAS;AAAA,MACzD,CAAC;AAGD,eAAS,iBAAiB,mBAAmB,EAAE,QAAQ,aAAW;AAChE,YAAI,CAAC,QAAQ,QAAQ,qBAAqB,GAAG;AAC3C,kBAAQ,aAAa,cAAc,MAAM;AACzC,kBAAQ,aAAa,uBAAuB,SAAS;AAAA,QACvD;AAGA,cAAM,WAAW,QAAQ;AACzB,YAAI,UAAU;AACZ,mBAAS,cAAc;AAAA,QACzB;AAAA,MACF,CAAC;AAGD,eAAS,iBAAiB,iBAAiB,EAAE,QAAQ,kBAAgB;AACnE,YAAI,OAAO,aAAa,iBAAiB,YAAY;AACnD,uBAAa,aAAa,SAAS,MAAM;AACzC,uBAAa,aAAa,uBAAuB,SAAS;AAAA,QAC5D;AACA,YAAI,OAAO,aAAa,iBAAiB,YAAY;AACnD,uBAAa,aAAa;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,gCAAgC;AACrC,UAAI,CAAC,OAAO;AAAY;AAExB,gBAAS,sBAAsB,OAAO,WAAW,8BAA8B;AAC/E,gBAAS,oBAAoB,CAAC,UAAU;AACtC,cAAM,gBAAgB,MAAM,UAAU,SAAS;AAC/C,kBAAS,0BAA0B,aAAa;AAAA,MAClD;AAGA,UAAI,UAAS,oBAAoB,kBAAkB;AACjD,kBAAS,oBAAoB,iBAAiB,UAAU,UAAS,iBAAiB;AAAA,MACpF,WAAW,UAAS,oBAAoB,aAAa;AAEnD,kBAAS,oBAAoB,YAAY,UAAS,iBAAiB;AAAA,MACrE;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,kCAAkC;AACvC,UAAI,UAAS,uBAAuB,UAAS,mBAAmB;AAC9D,YAAI,UAAS,oBAAoB,qBAAqB;AACpD,oBAAS,oBAAoB,oBAAoB,UAAU,UAAS,iBAAiB;AAAA,QACvF,WAAW,UAAS,oBAAoB,gBAAgB;AAEtD,oBAAS,oBAAoB,eAAe,UAAS,iBAAiB;AAAA,QACxE;AACA,kBAAS,sBAAsB;AAC/B,kBAAS,oBAAoB;AAAA,MAC/B;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,mBAAmB,aAAa;AACrC,qBAAe,mBAAmB,WAAW;AAG7C,eAAS,iBAAiB,mBAAmB,EAAE,QAAQ,aAAW;AAChE,cAAM,WAAW,QAAQ;AACzB,YAAI,YAAY,SAAS,eAAe;AACtC,mBAAS,cAAc;AAAA,QACzB;AAAA,MACF,CAAC;AAGD,eAAS,iBAAiB,iBAAiB,EAAE,QAAQ,kBAAgB;AACnE,YAAI,OAAO,aAAa,cAAc,YAAY;AAChD,gBAAM,WAAW,aAAa,UAAU;AACxC,cAAI,YAAY,SAAS,eAAe;AACtC,qBAAS,cAAc;AAAA,UACzB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWA,OAAO,gBAAgB,WAAW;AAChC,qBAAe,gBAAgB,SAAS;AAGxC,eAAS,iBAAiB,mBAAmB,EAAE,QAAQ,aAAW;AAChE,cAAM,WAAW,QAAQ;AACzB,YAAI,YAAY,SAAS,eAAe;AACtC,mBAAS,cAAc;AAAA,QACzB;AAAA,MACF,CAAC;AAED,eAAS,iBAAiB,iBAAiB,EAAE,QAAQ,kBAAgB;AACnE,YAAI,OAAO,aAAa,cAAc,YAAY;AAChD,gBAAM,WAAW,aAAa,UAAU;AACxC,cAAI,YAAY,SAAS,eAAe;AACtC,qBAAS,cAAc;AAAA,UACzB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA,IAKA,OAAO,sBAAsB;AAC3B,UAAI,UAAS;AAA4B;AAGzC,eAAS,iBAAiB,SAAS,CAAC,MAAM;AACxC,YAAI,EAAE,UAAU,EAAE,OAAO,aAAa,EAAE,OAAO,UAAU,SAAS,gBAAgB,GAAG;AACnF,gBAAM,UAAU,EAAE,OAAO,QAAQ,mBAAmB;AACpD,gBAAM,WAAW,mCAAS;AAC1B,cAAI;AAAU,qBAAS,YAAY,CAAC;AAAA,QACtC;AAAA,MACF,CAAC;AAGD,eAAS,iBAAiB,WAAW,CAAC,MAAM;AAC1C,YAAI,EAAE,UAAU,EAAE,OAAO,aAAa,EAAE,OAAO,UAAU,SAAS,gBAAgB,GAAG;AACnF,gBAAM,UAAU,EAAE,OAAO,QAAQ,mBAAmB;AACpD,gBAAM,WAAW,mCAAS;AAC1B,cAAI;AAAU,qBAAS,cAAc,CAAC;AAAA,QACxC;AAAA,MACF,CAAC;AAGD,eAAS,iBAAiB,UAAU,CAAC,MAAM;AACzC,YAAI,EAAE,UAAU,EAAE,OAAO,aAAa,EAAE,OAAO,UAAU,SAAS,gBAAgB,GAAG;AACnF,gBAAM,UAAU,EAAE,OAAO,QAAQ,mBAAmB;AACpD,gBAAM,WAAW,mCAAS;AAC1B,cAAI;AAAU,qBAAS,aAAa,CAAC;AAAA,QACvC;AAAA,MACF,GAAG,IAAI;AAGP,eAAS,iBAAiB,mBAAmB,CAAC,MAAM;AAClD,cAAM,gBAAgB,SAAS;AAC/B,YAAI,iBAAiB,cAAc,UAAU,SAAS,gBAAgB,GAAG;AACvE,gBAAM,UAAU,cAAc,QAAQ,mBAAmB;AACzD,gBAAM,WAAW,mCAAS;AAC1B,cAAI,UAAU;AAEZ,gBAAI,SAAS,QAAQ,aAAa,SAAS,UAAU;AACnD,uBAAS,aAAa;AAAA,YACxB;AAEA,yBAAa,SAAS,iBAAiB;AACvC,qBAAS,oBAAoB,WAAW,MAAM;AAC5C,uBAAS,cAAc;AAAA,YACzB,GAAG,EAAE;AAAA,UACP;AAAA,QACF;AAAA,MACF,CAAC;AAED,gBAAS,6BAA6B;AAAA,IACxC;AAAA,EACJ;AAnnDI;AAAA,gBAFE,WAEK,aAAY,oBAAI,QAAQ;AAC/B,gBAHE,WAGK,kBAAiB;AACxB,gBAJE,WAIK,8BAA6B;AACpC,gBALE,WAKK,iBAAgB;AACvB,gBANE,WAMK,uBAAsB;AAC7B;AAAA,gBAPE,WAOK,qBAAoB;AAP/B,MAAM,WAAN;AAwnDA,WAAS,iBAAiB;AAC1B,WAAS,mBAAmB;AAG5B,WAAS,SAAS,EAAE,OAAO,MAAM,SAAS,MAAM,EAAE;AAClD,WAAS,WAAW;AAGpB,WAAS,eAAe;AAGxB,MAAO,mBAAQ;", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons", "themeName"] } From b72e0202c33f0fdd7d0fdb71d2fb57bf24ee1f8e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:25:47 +0000 Subject: [PATCH 4/8] Optimize auto theme: global listener, shorter names, reduced duplication Co-authored-by: dido739 <152557154+dido739@users.noreply.github.com> --- README.md | 6 +- dist/overtype-webcomponent.esm.js | 216 ++++++++++++++------------- dist/overtype-webcomponent.js | 216 ++++++++++++++------------- dist/overtype-webcomponent.min.js | 80 +++++----- dist/overtype.cjs | 216 ++++++++++++++------------- dist/overtype.esm.js | 216 ++++++++++++++------------- dist/overtype.esm.js.map | 6 +- dist/overtype.js | 216 ++++++++++++++------------- dist/overtype.js.map | 6 +- dist/overtype.min.js | 100 ++++++------- src/overtype.js | 240 ++++++++++++++---------------- src/themes.js | 16 +- 12 files changed, 767 insertions(+), 767 deletions(-) diff --git a/README.md b/README.md index fee989a..e3e142d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OverType -A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay technique. Includes optional toolbar. ~98KB minified with all features. +A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay technique. Includes optional toolbar. ~97KB minified with all features. ## Live Examples @@ -20,7 +20,7 @@ A lightweight markdown editor library with perfect WYSIWYG alignment using an in - ⌨️ **Keyboard shortcuts** - Common markdown shortcuts (Cmd/Ctrl+B for bold, etc.) - 📱 **Mobile optimized** - Responsive design with mobile-specific styles - 🔄 **DOM persistence aware** - Recovers from existing DOM (perfect for HyperClay and similar platforms) -- 🚀 **Lightweight** - ~98KB minified +- 🚀 **Lightweight** - ~97KB minified - 🎯 **Optional toolbar** - Clean, minimal toolbar with all essential formatting - ✨ **Smart shortcuts** - Keyboard shortcuts with selection preservation - 📝 **Smart list continuation** - GitHub-style automatic list continuation on Enter @@ -36,7 +36,7 @@ We overlap an invisible textarea on top of styled output, giving the illusion of | Feature | OverType | HyperMD | Milkdown | TUI Editor | EasyMDE | |---------|----------|---------|----------|------------|---------| -| **Size** | ~98KB | 364.02 KB | 344.51 KB | 560.99 KB | 323.69 KB | +| **Size** | ~97KB | 364.02 KB | 344.51 KB | 560.99 KB | 323.69 KB | | **Dependencies** | Bundled | CodeMirror | ProseMirror + plugins | Multiple libs | CodeMirror | | **Setup** | Single file | Complex config | Build step required | Complex config | Moderate | | **Approach** | Invisible textarea | ContentEditable | ContentEditable | ContentEditable | CodeMirror | diff --git a/dist/overtype-webcomponent.esm.js b/dist/overtype-webcomponent.esm.js index 82e60e8..ce5cd5c 100644 --- a/dist/overtype-webcomponent.esm.js +++ b/dist/overtype-webcomponent.esm.js @@ -935,12 +935,14 @@ function getTheme(theme) { } return theme; } +var _mq = null; function resolveAutoTheme(themeName) { - if (themeName !== "auto") { + if (themeName !== "auto") return themeName; + if (!_mq && window.matchMedia) { + _mq = window.matchMedia("(prefers-color-scheme: dark)"); } - const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; - return isDarkMode ? "cave" : "solar"; + return (_mq == null ? void 0 : _mq.matches) ? "cave" : "solar"; } function themeToCSSVars(colors) { const vars = []; @@ -3373,7 +3375,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { - // Listener function for auto theme changes + // Global auto theme listener /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4073,12 +4075,11 @@ var _OverType = class _OverType { * @returns {this} Returns this for chaining */ setTheme(theme) { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.instanceTheme = theme; if (theme === "auto") { - this._setupAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - this._applyResolvedTheme(resolvedTheme); + this._setupAuto(); + this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; @@ -4098,13 +4099,12 @@ var _OverType = class _OverType { * @private * @param {string} themeName - Resolved theme name */ - _applyResolvedTheme(themeName) { + _applyTheme(themeName) { const themeObj = getTheme(themeName); this.container.setAttribute("data-theme", "auto"); this.container.setAttribute("data-resolved-theme", themeName); - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4112,33 +4112,37 @@ var _OverType = class _OverType { * Setup auto theme listener for instance * @private */ - _setupAutoThemeListener() { + _setupAuto() { if (!window.matchMedia) return; - this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - this.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - this._applyResolvedTheme(resolvedTheme); - }; - if (this.autoThemeMediaQuery.addEventListener) { - this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.addListener) { - this.autoThemeMediaQuery.addListener(this.autoThemeListener); + _OverType._autoInstances.add(this); + if (!_OverType._mq) { + _OverType._mq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._mqListener = (e) => { + const theme = e.matches ? "cave" : "solar"; + _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); + }; + if (_OverType._mq.addEventListener) { + _OverType._mq.addEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.addListener) { + _OverType._mq.addListener(_OverType._mqListener); + } } } /** * Clean up auto theme listener for instance * @private */ - _cleanupAutoThemeListener() { - if (this.autoThemeMediaQuery && this.autoThemeListener) { - if (this.autoThemeMediaQuery.removeEventListener) { - this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.removeListener) { - this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + _cleanupAuto() { + _OverType._autoInstances.delete(this); + if (_OverType._autoInstances.size === 0 && _OverType._mq) { + if (_OverType._mq.removeEventListener) { + _OverType._mq.removeEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.removeListener) { + _OverType._mq.removeListener(_OverType._mqListener); } - this.autoThemeMediaQuery = null; - this.autoThemeListener = null; + _OverType._mq = null; + _OverType._mqListener = null; } } /** @@ -4293,7 +4297,7 @@ var _OverType = class _OverType { * Destroy the editor instance */ destroy() { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4393,17 +4397,54 @@ var _OverType = class _OverType { document.head.appendChild(styleEl); _OverType.stylesInjected = true; } + /** + * Helper to update DOM elements with theme attributes + * @private + */ + static _updateThemeAttrs(themeName, isAuto = false) { + const containers = document.querySelectorAll(".overtype-container"); + const wrappers = document.querySelectorAll(".overtype-wrapper"); + containers.forEach((el) => { + if (isAuto) { + el.setAttribute("data-theme", "auto"); + el.setAttribute("data-resolved-theme", themeName); + } else { + el.setAttribute("data-theme", themeName); + } + }); + wrappers.forEach((wrapper) => { + var _a; + if (!wrapper.closest(".overtype-container")) { + if (isAuto) { + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); + } else { + wrapper.setAttribute("data-theme", themeName); + } + } + (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + }); + document.querySelectorAll("overtype-editor").forEach((wc) => { + var _a, _b, _c, _d; + if (isAuto) { + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); + } else { + (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); + } + (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + }); + } /** * Set global theme for all OverType instances * @param {string|Object} theme - Theme name or custom theme object * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - _OverType._cleanupGlobalAutoThemeListener(); + _OverType._cleanupGlobalAuto(); if (theme === "auto") { - _OverType._setupGlobalAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + _OverType._setupGlobalAuto(); + _OverType._applyGlobalTheme(resolveAutoTheme("auto"), customColors, true); } else { let themeObj = typeof theme === "string" ? getTheme(theme) : theme; if (customColors) { @@ -4411,33 +4452,10 @@ var _OverType = class _OverType { } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + const themeName = themeObj.name || theme; + if (themeName) { + _OverType._updateThemeAttrs(themeName); + } } } /** @@ -4445,69 +4463,47 @@ var _OverType = class _OverType { * @private * @param {string} themeName - Resolved theme name * @param {Object} customColors - Optional color overrides + * @param {boolean} isAuto - Whether this is an auto theme */ - static _applyGlobalResolvedTheme(themeName, customColors = null) { + static _applyGlobalTheme(themeName, customColors = null, isAuto = false) { let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - container.setAttribute("data-theme", "auto"); - container.setAttribute("data-resolved-theme", themeName); - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", "auto"); - webComponent.setAttribute("data-resolved-theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + _OverType._updateThemeAttrs(themeName, isAuto); } /** * Setup global auto theme listener * @private */ - static _setupGlobalAutoThemeListener() { - if (!window.matchMedia) + static _setupGlobalAuto() { + if (!window.matchMedia || _OverType._globalAutoMq) return; - _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - _OverType.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - _OverType._applyGlobalResolvedTheme(resolvedTheme); + _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._globalAutoListener = (e) => { + _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType.autoThemeMediaQuery.addEventListener) { - _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.addListener) { - _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + if (_OverType._globalAutoMq.addEventListener) { + _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.addListener) { + _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); } } /** * Clean up global auto theme listener * @private */ - static _cleanupGlobalAutoThemeListener() { - if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { - if (_OverType.autoThemeMediaQuery.removeEventListener) { - _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.removeListener) { - _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + static _cleanupGlobalAuto() { + if (_OverType._globalAutoMq && _OverType._globalAutoListener) { + if (_OverType._globalAutoMq.removeEventListener) { + _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.removeListener) { + _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); } - _OverType.autoThemeMediaQuery = null; - _OverType.autoThemeListener = null; + _OverType._globalAutoMq = null; + _OverType._globalAutoListener = null; } } /** @@ -4611,9 +4607,15 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); -__publicField(_OverType, "autoThemeMediaQuery", null); -// Media query for auto theme switching -__publicField(_OverType, "autoThemeListener", null); +__publicField(_OverType, "_mq", null); +// Shared media query for auto theme +__publicField(_OverType, "_mqListener", null); +// Shared listener +__publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); +// Track auto-themed instances +__publicField(_OverType, "_globalAutoMq", null); +// Global auto theme media query +__publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype-webcomponent.js b/dist/overtype-webcomponent.js index 9d01e26..0f51d43 100644 --- a/dist/overtype-webcomponent.js +++ b/dist/overtype-webcomponent.js @@ -958,12 +958,14 @@ var OverTypeEditor = (() => { } return theme; } + var _mq = null; function resolveAutoTheme(themeName) { - if (themeName !== "auto") { + if (themeName !== "auto") return themeName; + if (!_mq && window.matchMedia) { + _mq = window.matchMedia("(prefers-color-scheme: dark)"); } - const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; - return isDarkMode ? "cave" : "solar"; + return (_mq == null ? void 0 : _mq.matches) ? "cave" : "solar"; } function themeToCSSVars(colors) { const vars = []; @@ -3396,7 +3398,7 @@ ${blockSuffix}` : suffix; return false; } var _OverType = class _OverType { - // Listener function for auto theme changes + // Global auto theme listener /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4096,12 +4098,11 @@ ${blockSuffix}` : suffix; * @returns {this} Returns this for chaining */ setTheme(theme) { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.instanceTheme = theme; if (theme === "auto") { - this._setupAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - this._applyResolvedTheme(resolvedTheme); + this._setupAuto(); + this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; @@ -4121,13 +4122,12 @@ ${blockSuffix}` : suffix; * @private * @param {string} themeName - Resolved theme name */ - _applyResolvedTheme(themeName) { + _applyTheme(themeName) { const themeObj = getTheme(themeName); this.container.setAttribute("data-theme", "auto"); this.container.setAttribute("data-resolved-theme", themeName); - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4135,33 +4135,37 @@ ${blockSuffix}` : suffix; * Setup auto theme listener for instance * @private */ - _setupAutoThemeListener() { + _setupAuto() { if (!window.matchMedia) return; - this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - this.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - this._applyResolvedTheme(resolvedTheme); - }; - if (this.autoThemeMediaQuery.addEventListener) { - this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.addListener) { - this.autoThemeMediaQuery.addListener(this.autoThemeListener); + _OverType._autoInstances.add(this); + if (!_OverType._mq) { + _OverType._mq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._mqListener = (e) => { + const theme = e.matches ? "cave" : "solar"; + _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); + }; + if (_OverType._mq.addEventListener) { + _OverType._mq.addEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.addListener) { + _OverType._mq.addListener(_OverType._mqListener); + } } } /** * Clean up auto theme listener for instance * @private */ - _cleanupAutoThemeListener() { - if (this.autoThemeMediaQuery && this.autoThemeListener) { - if (this.autoThemeMediaQuery.removeEventListener) { - this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.removeListener) { - this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + _cleanupAuto() { + _OverType._autoInstances.delete(this); + if (_OverType._autoInstances.size === 0 && _OverType._mq) { + if (_OverType._mq.removeEventListener) { + _OverType._mq.removeEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.removeListener) { + _OverType._mq.removeListener(_OverType._mqListener); } - this.autoThemeMediaQuery = null; - this.autoThemeListener = null; + _OverType._mq = null; + _OverType._mqListener = null; } } /** @@ -4316,7 +4320,7 @@ ${blockSuffix}` : suffix; * Destroy the editor instance */ destroy() { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4416,17 +4420,54 @@ ${blockSuffix}` : suffix; document.head.appendChild(styleEl); _OverType.stylesInjected = true; } + /** + * Helper to update DOM elements with theme attributes + * @private + */ + static _updateThemeAttrs(themeName, isAuto = false) { + const containers = document.querySelectorAll(".overtype-container"); + const wrappers = document.querySelectorAll(".overtype-wrapper"); + containers.forEach((el) => { + if (isAuto) { + el.setAttribute("data-theme", "auto"); + el.setAttribute("data-resolved-theme", themeName); + } else { + el.setAttribute("data-theme", themeName); + } + }); + wrappers.forEach((wrapper) => { + var _a; + if (!wrapper.closest(".overtype-container")) { + if (isAuto) { + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); + } else { + wrapper.setAttribute("data-theme", themeName); + } + } + (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + }); + document.querySelectorAll("overtype-editor").forEach((wc) => { + var _a, _b, _c, _d; + if (isAuto) { + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); + } else { + (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); + } + (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + }); + } /** * Set global theme for all OverType instances * @param {string|Object} theme - Theme name or custom theme object * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - _OverType._cleanupGlobalAutoThemeListener(); + _OverType._cleanupGlobalAuto(); if (theme === "auto") { - _OverType._setupGlobalAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + _OverType._setupGlobalAuto(); + _OverType._applyGlobalTheme(resolveAutoTheme("auto"), customColors, true); } else { let themeObj = typeof theme === "string" ? getTheme(theme) : theme; if (customColors) { @@ -4434,33 +4475,10 @@ ${blockSuffix}` : suffix; } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + const themeName = themeObj.name || theme; + if (themeName) { + _OverType._updateThemeAttrs(themeName); + } } } /** @@ -4468,69 +4486,47 @@ ${blockSuffix}` : suffix; * @private * @param {string} themeName - Resolved theme name * @param {Object} customColors - Optional color overrides + * @param {boolean} isAuto - Whether this is an auto theme */ - static _applyGlobalResolvedTheme(themeName, customColors = null) { + static _applyGlobalTheme(themeName, customColors = null, isAuto = false) { let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - container.setAttribute("data-theme", "auto"); - container.setAttribute("data-resolved-theme", themeName); - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", "auto"); - webComponent.setAttribute("data-resolved-theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + _OverType._updateThemeAttrs(themeName, isAuto); } /** * Setup global auto theme listener * @private */ - static _setupGlobalAutoThemeListener() { - if (!window.matchMedia) + static _setupGlobalAuto() { + if (!window.matchMedia || _OverType._globalAutoMq) return; - _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - _OverType.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - _OverType._applyGlobalResolvedTheme(resolvedTheme); + _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._globalAutoListener = (e) => { + _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType.autoThemeMediaQuery.addEventListener) { - _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.addListener) { - _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + if (_OverType._globalAutoMq.addEventListener) { + _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.addListener) { + _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); } } /** * Clean up global auto theme listener * @private */ - static _cleanupGlobalAutoThemeListener() { - if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { - if (_OverType.autoThemeMediaQuery.removeEventListener) { - _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.removeListener) { - _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + static _cleanupGlobalAuto() { + if (_OverType._globalAutoMq && _OverType._globalAutoListener) { + if (_OverType._globalAutoMq.removeEventListener) { + _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.removeListener) { + _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); } - _OverType.autoThemeMediaQuery = null; - _OverType.autoThemeListener = null; + _OverType._globalAutoMq = null; + _OverType._globalAutoListener = null; } } /** @@ -4634,9 +4630,15 @@ ${blockSuffix}` : suffix; __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); - __publicField(_OverType, "autoThemeMediaQuery", null); - // Media query for auto theme switching - __publicField(_OverType, "autoThemeListener", null); + __publicField(_OverType, "_mq", null); + // Shared media query for auto theme + __publicField(_OverType, "_mqListener", null); + // Shared listener + __publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); + // Track auto-themed instances + __publicField(_OverType, "_globalAutoMq", null); + // Global auto theme media query + __publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype-webcomponent.min.js b/dist/overtype-webcomponent.min.js index 60bfe6b..5ab20ab 100644 --- a/dist/overtype-webcomponent.min.js +++ b/dist/overtype-webcomponent.min.js @@ -5,15 +5,15 @@ * @author David Miranda * https://github.com/panphora/overtype */ -var OverTypeEditor=(()=>{var j=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var Ve=Object.getOwnPropertyNames;var Ue=Object.prototype.hasOwnProperty;var De=(n,e,t)=>e in n?j(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var qe=(n,e)=>{for(var t in e)j(n,t,{get:e[t],enumerable:!0})},We=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Ve(e))!Ue.call(n,o)&&o!==t&&j(n,o,{get:()=>e[o],enumerable:!(i=Fe(e,o))||i.enumerable});return n};var Ke=n=>We(j({},"__esModule",{value:!0}),n);var T=(n,e,t)=>(De(n,typeof e!="symbol"?e+"":e,t),t);var dt={};qe(dt,{default:()=>pt});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,i=>t[i])}static preserveIndentation(e,t){let o=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,o)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,i,o)=>{let r=i.length;return`${i} ${o}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,i)=>`> ${i}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,i,o,r)=>`${i}
  • ${o} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(i,o,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${o}
  • ${s}
  • `}else return`${o}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,i,o,r)=>`${i}
  • ${o} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),i=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>i.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,i,o)=>{let r=`--link-${this.linkIndex++}`;return`
    [${i}](${o})`})}static identifyAndProtectSanctuaries(e){let t=new Map,i=0,o=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,u=h+a[2].length;r.push({start:h,end:u})}let c=new RegExp("(?p>=g.start&&h<=g.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((p,h)=>h.index-p.index),l.forEach(p=>{let h=`\uE000${i++}\uE001`;t.set(h,{type:"code",original:p.match,openTicks:p.openTicks,content:p.content,closeTicks:p.closeTicks}),o=o.substring(0,p.index)+h+o.substring(p.index+p.match.length)}),o=o.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(p,h,u)=>{let g=`\uE000${i++}\uE001`;return t.set(g,{type:"link",original:p,linkText:h,url:u}),g}),{protectedText:o,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((o,r)=>{let s=e.indexOf(o),a=e.indexOf(r);return s-a}).forEach(o=>{let r=t.get(o),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,p)=>{if(a.includes(p)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(p,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let c=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(o,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:i}=this.identifyAndProtectSanctuaries(e),o=t;return o=this.parseStrikethrough(o),o=this.parseBold(o),o=this.parseItalic(o),o=this.restoreAndTransformSanctuaries(o,i),o}static parseLine(e,t=!1){let i=this.escapeHtml(e);i=this.preserveIndentation(i,e);let o=this.parseHorizontalRule(i);if(o)return o;let r=this.parseCodeBlock(i);return r||(i=this.parseHeader(i),i=this.parseBlockquote(i),i=this.parseTaskList(i,t),i=this.parseBulletList(i),i=this.parseNumberedList(i),i=this.parseInlineElements(i),i.trim()===""?"
     
    ":`
    ${i}
    `)}static parse(e,t=-1,i=!1,o,r=!1){this.resetLinkIndex();let s=e.split(` -`),a=!1,d=s.map((l,p)=>{if(i&&p===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let u=this.escapeHtml(l);return`
    ${this.preserveIndentation(u,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,o)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let i=document.createElement("div");i.innerHTML=e;let o=null,r=null,s=null,a=!1,c=Array.from(i.children);for(let d=0;d0&&(s._codeContent+=` -`);let g=l.textContent.replace(/\u00A0/g," ");s._codeContent+=g,u.textContent.length>0&&(u.textContent+=` -`),u.textContent+=g,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let u=h.classList.contains("bullet-list"),g=h.classList.contains("ordered-list");if(!u&&!g){o=null,r=null;continue}let f=u?"ul":"ol";(!o||r!==f)&&(o=document.createElement(f),i.insertBefore(o,l),r=f);let v=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))v.push(y.cloneNode(!0));else if(y===h)break;v.forEach(y=>{h.insertBefore(y,h.firstChild)}),o.appendChild(h),l.remove()}else o=null,r=null}return i.innerHTML}static postProcessHTMLManual(e,t){let i=e;i=i.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    • /,`
    • ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),i=i.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    2. /,`
    3. ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let o=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return i=i.replace(o,(r,s,a,c)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(v=>v.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` -`),p=s.slice(3).trim(),h=p?` class="language-${p}"`:"",u=l,g=t||this.codeHighlighter;if(g)try{let v=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=g(v,p);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(u=y)}catch(v){console.warn("Code highlighting failed:",v)}let f=`
    ${s}
    `;return f+=`
    ${u}
    `,f+=`
    ${c}
    `,f}),i}static getListContext(e,t){let i=e.split(` -`),o=0,r=0,s=0;for(let h=0;h=t){r=h,s=o;break}o+=u+1}let a=i[r],c=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:c,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:c,markerEndPos:s+l[1].length+l[2].length+1};let p=a.match(this.LIST_PATTERNS.numbered);return p?{inList:!0,listType:"numbered",indent:p[1],marker:parseInt(p[2]),content:p[3],lineStart:s,lineEnd:c,markerEndPos:s+p[1].length+p[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:c,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` -`),i=new Map,o=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let c=a[1],d=c.length,l=a[3];o||i.clear();let p=(i.get(d)||0)+1;i.set(d,p);for(let[h]of i)h>d&&i.delete(h);return o=!0,`${c}${p}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(o=!1,i.clear()),s}).join(` -`)}};T(S,"linkIndex",0),T(S,"codeHighlighter",null),T(S,"customSyntax",null),T(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let o=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(o="toggleBold");break;case"i":e.shiftKey||(o="toggleItalic");break;case"k":e.shiftKey||(o="insertLink");break;case"7":e.shiftKey&&(o="toggleNumberedList");break;case"8":e.shiftKey&&(o="toggleBulletList");break}return o?(e.preventDefault(),this.editor.performAction(o,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},te={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},Qe={name:"auto",colors:A.colors},ie={solar:A,cave:te,auto:Qe,light:A,dark:te};function E(n){return typeof n=="string"?{...ie[n]||ie.solar,name:n}:n}function Q(n){return n!=="auto"?n:window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"cave":"solar"}function B(n){let e=[];for(let[t,i]of Object.entries(n)){let o=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${o}: ${i};`)}return e.join(` -`)}function G(n,e={}){return{...n,colors:{...n.colors,...e}}}function R(n={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:i='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:o="20px",theme:r=null,mobile:s={}}=n,a=Object.keys(s).length>0?` +var OverTypeEditor=(()=>{var F=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var qe=Object.getOwnPropertyNames;var Ue=Object.prototype.hasOwnProperty;var De=(n,e,t)=>e in n?F(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var We=(n,e)=>{for(var t in e)F(n,t,{get:e[t],enumerable:!0})},Ke=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of qe(e))!Ue.call(n,o)&&o!==t&&F(n,o,{get:()=>e[o],enumerable:!(i=Ve(e,o))||i.enumerable});return n};var Ge=n=>Ke(F({},"__esModule",{value:!0}),n);var E=(n,e,t)=>(De(n,typeof e!="symbol"?e+"":e,t),t);var ht={};We(ht,{default:()=>dt});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,i=>t[i])}static preserveIndentation(e,t){let o=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,o)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,i,o)=>{let r=i.length;return`${i} ${o}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,i)=>`> ${i}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,i,o,r)=>`${i}
  • ${o} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(i,o,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${o}
  • ${s}
  • `}else return`${o}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,i,o,r)=>`${i}
  • ${o} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),i=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>i.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,i,o)=>{let r=`--link-${this.linkIndex++}`;return`[${i}](${o})`})}static identifyAndProtectSanctuaries(e){let t=new Map,i=0,o=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let u=a.index+a[0].indexOf("](")+2,m=u+a[2].length;r.push({start:u,end:m})}let c=new RegExp("(?p>=g.start&&u<=g.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((p,u)=>u.index-p.index),l.forEach(p=>{let u=`\uE000${i++}\uE001`;t.set(u,{type:"code",original:p.match,openTicks:p.openTicks,content:p.content,closeTicks:p.closeTicks}),o=o.substring(0,p.index)+u+o.substring(p.index+p.match.length)}),o=o.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(p,u,m)=>{let g=`\uE000${i++}\uE001`;return t.set(g,{type:"link",original:p,linkText:u,url:m}),g}),{protectedText:o,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((o,r)=>{let s=e.indexOf(o),a=e.indexOf(r);return s-a}).forEach(o=>{let r=t.get(o),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,p)=>{if(a.includes(p)&&l.type==="code"){let u=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(p,u)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let c=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(o,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:i}=this.identifyAndProtectSanctuaries(e),o=t;return o=this.parseStrikethrough(o),o=this.parseBold(o),o=this.parseItalic(o),o=this.restoreAndTransformSanctuaries(o,i),o}static parseLine(e,t=!1){let i=this.escapeHtml(e);i=this.preserveIndentation(i,e);let o=this.parseHorizontalRule(i);if(o)return o;let r=this.parseCodeBlock(i);return r||(i=this.parseHeader(i),i=this.parseBlockquote(i),i=this.parseTaskList(i,t),i=this.parseBulletList(i),i=this.parseNumberedList(i),i=this.parseInlineElements(i),i.trim()===""?"
     
    ":`
    ${i}
    `)}static parse(e,t=-1,i=!1,o,r=!1){this.resetLinkIndex();let s=e.split(` +`),a=!1,d=s.map((l,p)=>{if(i&&p===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let m=this.escapeHtml(l);return`
    ${this.preserveIndentation(m,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,o)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let i=document.createElement("div");i.innerHTML=e;let o=null,r=null,s=null,a=!1,c=Array.from(i.children);for(let d=0;d0&&(s._codeContent+=` +`);let g=l.textContent.replace(/\u00A0/g," ");s._codeContent+=g,m.textContent.length>0&&(m.textContent+=` +`),m.textContent+=g,l.remove();continue}let u=null;if(l.tagName==="DIV"&&(u=l.querySelector("li")),u){let m=u.classList.contains("bullet-list"),g=u.classList.contains("ordered-list");if(!m&&!g){o=null,r=null;continue}let f=m?"ul":"ol";(!o||r!==f)&&(o=document.createElement(f),i.insertBefore(o,l),r=f);let v=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))v.push(y.cloneNode(!0));else if(y===u)break;v.forEach(y=>{u.insertBefore(y,u.firstChild)}),o.appendChild(u),l.remove()}else o=null,r=null}return i.innerHTML}static postProcessHTMLManual(e,t){let i=e;i=i.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    • /,`
    • ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),i=i.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    2. /,`
    3. ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let o=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return i=i.replace(o,(r,s,a,c)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(v=>v.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` +`),p=s.slice(3).trim(),u=p?` class="language-${p}"`:"",m=l,g=t||this.codeHighlighter;if(g)try{let v=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=g(v,p);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(m=y)}catch(v){console.warn("Code highlighting failed:",v)}let f=`
    ${s}
    `;return f+=`
    ${m}
    `,f+=`
    ${c}
    `,f}),i}static getListContext(e,t){let i=e.split(` +`),o=0,r=0,s=0;for(let u=0;u=t){r=u,s=o;break}o+=m+1}let a=i[r],c=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:c,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:c,markerEndPos:s+l[1].length+l[2].length+1};let p=a.match(this.LIST_PATTERNS.numbered);return p?{inList:!0,listType:"numbered",indent:p[1],marker:parseInt(p[2]),content:p[3],lineStart:s,lineEnd:c,markerEndPos:s+p[1].length+p[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:c,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` +`),i=new Map,o=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let c=a[1],d=c.length,l=a[3];o||i.clear();let p=(i.get(d)||0)+1;i.set(d,p);for(let[u]of i)u>d&&i.delete(u);return o=!0,`${c}${p}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(o=!1,i.clear()),s}).join(` +`)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let o=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(o="toggleBold");break;case"i":e.shiftKey||(o="toggleItalic");break;case"k":e.shiftKey||(o="insertLink");break;case"7":e.shiftKey&&(o="toggleNumberedList");break;case"8":e.shiftKey&&(o="toggleBulletList");break}return o?(e.preventDefault(),this.editor.performAction(o,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ie={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},Ze={name:"auto",colors:A.colors},ne={solar:A,cave:ie,auto:Ze,light:A,dark:ie};function _(n){return typeof n=="string"?{...ne[n]||ne.solar,name:n}:n}var O=null;function Z(n){return n!=="auto"?n:(!O&&window.matchMedia&&(O=window.matchMedia("(prefers-color-scheme: dark)")),O!=null&&O.matches?"cave":"solar")}function B(n){let e=[];for(let[t,i]of Object.entries(n)){let o=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${o}: ${i};`)}return e.join(` +`)}function J(n,e={}){return{...n,colors:{...n.colors,...e}}}function R(n={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:i='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:o="20px",theme:r=null,mobile:s={}}=n,a=Object.keys(s).length>0?` @media (max-width: 640px) { .overtype-wrapper .overtype-input, .overtype-wrapper .overtype-preview { @@ -861,28 +861,28 @@ var OverTypeEditor=(()=>{var j=Object.defineProperty;var Fe=Object.getOwnPropert } ${a} - `}var Ge=Object.defineProperty,ne=Object.getOwnPropertySymbols,Ze=Object.prototype.hasOwnProperty,Je=Object.prototype.propertyIsEnumerable,oe=(n,e,t)=>e in n?Ge(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,re=(n,e)=>{for(var t in e||(e={}))Ze.call(e,t)&&oe(n,t,e[t]);if(ne)for(var t of ne(e))Je.call(e,t)&&oe(n,t,e[t]);return n},_={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Xe(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function M(n){return re(re({},Xe()),n)}var V=!1;function Ye(){return V}function b(n,e,t){V&&(console.group(`\u{1F50D} ${n}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function F(n,e){if(!V)return;let t=n.value.slice(n.selectionStart,n.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let i=n.value.slice(Math.max(0,n.selectionStart-10),n.selectionStart),o=n.value.slice(n.selectionEnd,Math.min(n.value.length,n.selectionEnd+10));console.log("Context:",JSON.stringify(i)+"[SELECTION]"+JSON.stringify(o)),console.groupEnd()}function ce(n){V&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(n.text)),console.log("New selection:",`${n.selectionStart}-${n.selectionEnd}`),console.groupEnd())}var H=null;function I(n,{text:e,selectionStart:t,selectionEnd:i}){let o=Ye();o&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",i)),n.focus();let r=n.selectionStart,s=n.selectionEnd,a=n.value.slice(0,r),c=n.value.slice(s);o&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(n.value.slice(r,s))));let d=n.value,l=r!==s;if(H===null||H===!0){n.contentEditable="true";try{H=document.execCommand("insertText",!1,e),o&&console.log("execCommand returned:",H,"for text with",e.split(` -`).length,"lines")}catch(p){H=!1,o&&console.log("execCommand threw error:",p)}n.contentEditable="false"}if(o&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let p=a+e+c,h=n.value;o&&(console.log("Expected length:",p.length),console.log("Actual length:",h.length)),h!==p&&o&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(p.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!H)if(o&&console.log("Using manual insertion"),n.value===d){o&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(p){}n.value=a+e+c;try{document.execCommand("ms-endUndoUnit")}catch(p){}n.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else o&&console.log("Value was changed by execCommand, skipping manual insertion");o&&console.log("Setting selection range:",t,i),t!=null&&i!=null?n.setSelectionRange(t,i):n.setSelectionRange(r,n.selectionEnd),o&&(console.log("Final value length:",n.value.length),console.groupEnd())}function se(n){return n.trim().split(` -`).length>1}function et(n,e){let t=e;for(;n[t]&&n[t-1]!=null&&!n[t-1].match(/\s/);)t--;return t}function tt(n,e,t){let i=e,o=t?/\n/:/\s/;for(;n[i]&&!n[i].match(o);)i++;return i}function pe(n){let e=n.value.split(` -`),t=0;for(let i=0;i=t&&n.selectionStart=t&&n.selectionEnde in n?Je(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,se=(n,e)=>{for(var t in e||(e={}))Qe.call(e,t)&&re(n,t,e[t]);if(oe)for(var t of oe(e))Xe.call(e,t)&&re(n,t,e[t]);return n},C={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Ye(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function M(n){return se(se({},Ye()),n)}var q=!1;function et(){return q}function b(n,e,t){q&&(console.group(`\u{1F50D} ${n}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function V(n,e){if(!q)return;let t=n.value.slice(n.selectionStart,n.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let i=n.value.slice(Math.max(0,n.selectionStart-10),n.selectionStart),o=n.value.slice(n.selectionEnd,Math.min(n.value.length,n.selectionEnd+10));console.log("Context:",JSON.stringify(i)+"[SELECTION]"+JSON.stringify(o)),console.groupEnd()}function pe(n){q&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(n.text)),console.log("New selection:",`${n.selectionStart}-${n.selectionEnd}`),console.groupEnd())}var H=null;function $(n,{text:e,selectionStart:t,selectionEnd:i}){let o=et();o&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",i)),n.focus();let r=n.selectionStart,s=n.selectionEnd,a=n.value.slice(0,r),c=n.value.slice(s);o&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(n.value.slice(r,s))));let d=n.value,l=r!==s;if(H===null||H===!0){n.contentEditable="true";try{H=document.execCommand("insertText",!1,e),o&&console.log("execCommand returned:",H,"for text with",e.split(` +`).length,"lines")}catch(p){H=!1,o&&console.log("execCommand threw error:",p)}n.contentEditable="false"}if(o&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let p=a+e+c,u=n.value;o&&(console.log("Expected length:",p.length),console.log("Actual length:",u.length)),u!==p&&o&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(p.slice(0,100))),console.log("Actual:",JSON.stringify(u.slice(0,100))))}if(!H)if(o&&console.log("Using manual insertion"),n.value===d){o&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(p){}n.value=a+e+c;try{document.execCommand("ms-endUndoUnit")}catch(p){}n.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else o&&console.log("Value was changed by execCommand, skipping manual insertion");o&&console.log("Setting selection range:",t,i),t!=null&&i!=null?n.setSelectionRange(t,i):n.setSelectionRange(r,n.selectionEnd),o&&(console.log("Final value length:",n.value.length),console.groupEnd())}function ae(n){return n.trim().split(` +`).length>1}function tt(n,e){let t=e;for(;n[t]&&n[t-1]!=null&&!n[t-1].match(/\s/);)t--;return t}function it(n,e,t){let i=e,o=t?/\n/:/\s/;for(;n[i]&&!n[i].match(o);)i++;return i}function de(n){let e=n.value.split(` +`),t=0;for(let i=0;i=t&&n.selectionStart=t&&n.selectionEnd0&&s[a-1]!==` `;)a--;if(r){let d=i;for(;d0?`${s} -`:o,y=se(f)&&a&&a.length>0?` -${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(v=` ${v}`)}f=it(n,v,y,e.multiline);let w=n.selectionStart,x=n.selectionEnd,$=c&&c.length>0&&y.indexOf(c)>-1&&f.length>0;if(p){let L=Z(n);t=L.newlinesToAppend,i=L.newlinesToPrepend,v=t+o,y+=i}if(f.startsWith(v)&&f.endsWith(y)){let L=f.slice(v.length,f.length-y.length);if(u===g){let C=u-v.length;C=Math.max(C,w),C=Math.min(C,w+L.length),w=x=C}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if($)if(l&&l.length>0&&f.match(l)){y=y.replace(c,f);let L=v+y;return w=x=w+v.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;return w=w+v.length+f.length+y.indexOf(c),x=w+c.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;w=u+v.length,x=g+v.length;let C=f.match(/^\s*|\s*$/g);if(h&&C){let Y=C[0]||"",ee=C[1]||"";L=Y+v+f.trim()+y+ee,w+=Y.length,x-=ee.length}return{text:L,selectionStart:w,selectionEnd:x}}}function de(n,e){let{prefix:t,suffix:i,surroundWithNewlines:o}=e,r=n.value.slice(n.selectionStart,n.selectionEnd),s=n.selectionStart,a=n.selectionEnd,c=r.split(` +`;)d++;n.selectionStart=a,n.selectionEnd=d}else de(n);let c=e(n);if(t.adjustSelection){let l=n.value.slice(n.selectionStart,n.selectionEnd).startsWith(t.prefix),p=t.adjustSelection(l,i,o,a);c.selectionStart=p.start,c.selectionEnd=p.end}else if(t.prefix){let l=n.value.slice(n.selectionStart,n.selectionEnd).startsWith(t.prefix);r?l?(c.selectionStart=Math.max(i-t.prefix.length,a),c.selectionEnd=c.selectionStart):(c.selectionStart=i+t.prefix.length,c.selectionEnd=c.selectionStart):l?(c.selectionStart=Math.max(i-t.prefix.length,a),c.selectionEnd=Math.max(o-t.prefix.length,a)):(c.selectionStart=i+t.prefix.length,c.selectionEnd=o+t.prefix.length)}return c}function D(n,e){let t,i,{prefix:o,suffix:r,blockPrefix:s,blockSuffix:a,replaceNext:c,prefixSpace:d,scanFor:l,surroundWithNewlines:p,trimFirst:u}=e,m=n.selectionStart,g=n.selectionEnd,f=n.value.slice(n.selectionStart,n.selectionEnd),v=ae(f)&&s&&s.length>0?`${s} +`:o,y=ae(f)&&a&&a.length>0?` +${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(v=` ${v}`)}f=nt(n,v,y,e.multiline);let w=n.selectionStart,x=n.selectionEnd,I=c&&c.length>0&&y.indexOf(c)>-1&&f.length>0;if(p){let L=Q(n);t=L.newlinesToAppend,i=L.newlinesToPrepend,v=t+o,y+=i}if(f.startsWith(v)&&f.endsWith(y)){let L=f.slice(v.length,f.length-y.length);if(m===g){let T=m-v.length;T=Math.max(T,w),T=Math.min(T,w+L.length),w=x=T}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if(I)if(l&&l.length>0&&f.match(l)){y=y.replace(c,f);let L=v+y;return w=x=w+v.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;return w=w+v.length+f.length+y.indexOf(c),x=w+c.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;w=m+v.length,x=g+v.length;let T=f.match(/^\s*|\s*$/g);if(u&&T){let ee=T[0]||"",te=T[1]||"";L=ee+v+f.trim()+y+te,w+=ee.length,x-=te.length}return{text:L,selectionStart:w,selectionEnd:x}}}function he(n,e){let{prefix:t,suffix:i,surroundWithNewlines:o}=e,r=n.value.slice(n.selectionStart,n.selectionEnd),s=n.selectionStart,a=n.selectionEnd,c=r.split(` `);if(c.every(l=>l.startsWith(t)&&(!i||l.endsWith(i))))r=c.map(l=>{let p=l.slice(t.length);return i&&(p=p.slice(0,p.length-i.length)),p}).join(` `),a=s+r.length;else if(r=c.map(l=>t+l+(i||"")).join(` -`),o){let{newlinesToAppend:l,newlinesToPrepend:p}=Z(n);s+=l.length,a=s+r.length,r=l+r+p}return{text:r,selectionStart:s,selectionEnd:a}}function ae(n){let e=n.split(` +`),o){let{newlinesToAppend:l,newlinesToPrepend:p}=Q(n);s+=l.length,a=s+r.length,r=l+r+p}return{text:r,selectionStart:s,selectionEnd:a}}function le(n){let e=n.split(` `),t=/^\d+\.\s+/,i=e.every(r=>t.test(r)),o=e;return i&&(o=e.map(r=>r.replace(t,""))),{text:o.join(` -`),processed:i}}function le(n){let e=n.split(` +`),processed:i}}function ce(n){let e=n.split(` `),t="- ",i=e.every(r=>r.startsWith(t)),o=e;return i&&(o=e.map(r=>r.slice(t.length))),{text:o.join(` -`),processed:i}}function O(n,e){return e?"- ":`${n+1}. `}function nt(n,e){let t,i,o;return n.orderedList?(t=ae(e),i=le(t.text),o=i.text):(t=le(e),i=ae(t.text),o=i.text),[t,i,o]}function ot(n,e){let t=n.selectionStart===n.selectionEnd,i=n.selectionStart,o=n.selectionEnd;pe(n);let r=n.value.slice(n.selectionStart,n.selectionEnd),[s,a,c]=nt(e,r),d=c.split(` -`).map((f,v)=>`${O(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+O(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+O(y,!e.unorderedList).length,0);if(s.processed)return t?(i=Math.max(i-O(0,e.unorderedList).length,0),o=i):(i=n.selectionStart,o=n.selectionEnd-l),{text:c,selectionStart:i,selectionEnd:o};let{newlinesToAppend:h,newlinesToPrepend:u}=Z(n),g=h+d.join(` -`)+u;return t?(i=Math.max(i+O(0,e.unorderedList).length+h.length,0),o=i):a.processed?(i=Math.max(n.selectionStart+h.length,0),o=n.selectionEnd+h.length+l-p):(i=Math.max(n.selectionStart+h.length,0),o=n.selectionEnd+h.length+l),{text:g,selectionStart:i,selectionEnd:o}}function he(n,e){let t=U(n,i=>ot(i,e),{adjustSelection:(i,o,r,s)=>{let a=n.value.slice(s,n.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),h=e.orderedList&&l||e.unorderedList&&p;if(o===r)if(h){let u=a.match(e.orderedList?c:d),g=u?u[0].length:0;return{start:Math.max(o-g,s),end:Math.max(o-g,s)}}else if(l||p){let u=a.match(l?c:d),g=u?u[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:o+v}}else{let u=e.unorderedList?2:3;return{start:o+u,end:o+u}}else if(h){let u=a.match(e.orderedList?c:d),g=u?u[0].length:0;return{start:Math.max(o-g,s),end:Math.max(r-g,s)}}else if(l||p){let u=a.match(l?c:d),g=u?u[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:r+v}}else{let u=e.unorderedList?2:3;return{start:o+u,end:r+u}}}});I(n,t)}function rt(n){if(!n)return[];let e=[],{selectionStart:t,selectionEnd:i,value:o}=n,r=o.split(` -`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(o.length,i+10),l=o.slice(c,d);if(l.includes("**")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("**"),g=h.indexOf("**");u!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("_"),g=h.indexOf("_");u!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100));p.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=o.slice(Math.max(0,t-100),t),h=o.slice(i,Math.min(o.length,i+100)),u=p.lastIndexOf("["),g=h.indexOf("]");u!==-1&&g!==-1&&o.slice(i+g+1,i+g+10).startsWith("(")&&e.push("link")}return e}function ue(n){if(!n||n.disabled||n.readOnly)return;b("toggleBold","Starting"),F(n,"Before");let e=M(_.bold),t=D(n,e);ce(t),I(n,t),F(n,"After")}function me(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.italic),t=D(n,e);I(n,t)}function fe(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.code),t=D(n,e);I(n,t)}function ge(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),i=M(_.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(i.suffix=`](${t})`,i.replaceNext=""):e.url&&(i.suffix=`](${e.url})`,i.replaceNext=""),e.text&&!t){let s=n.selectionStart;n.value=n.value.slice(0,s)+e.text+n.value.slice(s),n.selectionStart=s,n.selectionEnd=s+e.text.length}let r=D(n,i);I(n,r)}function ve(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.bulletList);he(n,e)}function ye(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.numberedList);he(n,e)}function be(n){if(!n||n.disabled||n.readOnly)return;b("toggleQuote","Starting"),F(n,"Initial");let e=M(_.quote),t=U(n,i=>de(i,e),{prefix:e.prefix});ce(t),I(n,t),F(n,"Final")}function J(n){if(!n||n.disabled||n.readOnly)return;let e=M(_.taskList),t=U(n,i=>de(i,e),{prefix:e.prefix});I(n,t)}function X(n,e=1,t=!1){if(!n||n.disabled||n.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${n.selectionStart}-${n.selectionEnd}`);let i=`header${e===1?"1":e}`,o=M(_[i]||_.header1);b("insertHeader",`Style prefix: "${o.prefix}"`);let r=n.value,s=n.selectionStart,a=n.selectionEnd,c=s;for(;c>0&&r[c-1]!==` +`),processed:i}}function N(n,e){return e?"- ":`${n+1}. `}function ot(n,e){let t,i,o;return n.orderedList?(t=le(e),i=ce(t.text),o=i.text):(t=ce(e),i=le(t.text),o=i.text),[t,i,o]}function rt(n,e){let t=n.selectionStart===n.selectionEnd,i=n.selectionStart,o=n.selectionEnd;de(n);let r=n.value.slice(n.selectionStart,n.selectionEnd),[s,a,c]=ot(e,r),d=c.split(` +`).map((f,v)=>`${N(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+N(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+N(y,!e.unorderedList).length,0);if(s.processed)return t?(i=Math.max(i-N(0,e.unorderedList).length,0),o=i):(i=n.selectionStart,o=n.selectionEnd-l),{text:c,selectionStart:i,selectionEnd:o};let{newlinesToAppend:u,newlinesToPrepend:m}=Q(n),g=u+d.join(` +`)+m;return t?(i=Math.max(i+N(0,e.unorderedList).length+u.length,0),o=i):a.processed?(i=Math.max(n.selectionStart+u.length,0),o=n.selectionEnd+u.length+l-p):(i=Math.max(n.selectionStart+u.length,0),o=n.selectionEnd+u.length+l),{text:g,selectionStart:i,selectionEnd:o}}function ue(n,e){let t=U(n,i=>rt(i,e),{adjustSelection:(i,o,r,s)=>{let a=n.value.slice(s,n.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),u=e.orderedList&&l||e.unorderedList&&p;if(o===r)if(u){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(o-g,s),end:Math.max(o-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:o+v}}else{let m=e.unorderedList?2:3;return{start:o+m,end:o+m}}else if(u){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(o-g,s),end:Math.max(r-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:o+m,end:r+m}}}});$(n,t)}function st(n){if(!n)return[];let e=[],{selectionStart:t,selectionEnd:i,value:o}=n,r=o.split(` +`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(o.length,i+10),l=o.slice(c,d);if(l.includes("**")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("**"),g=u.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("_"),g=u.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100));p.includes("`")&&u.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("["),g=u.indexOf("]");m!==-1&&g!==-1&&o.slice(i+g+1,i+g+10).startsWith("(")&&e.push("link")}return e}function me(n){if(!n||n.disabled||n.readOnly)return;b("toggleBold","Starting"),V(n,"Before");let e=M(C.bold),t=D(n,e);pe(t),$(n,t),V(n,"After")}function fe(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.italic),t=D(n,e);$(n,t)}function ge(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.code),t=D(n,e);$(n,t)}function ve(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),i=M(C.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(i.suffix=`](${t})`,i.replaceNext=""):e.url&&(i.suffix=`](${e.url})`,i.replaceNext=""),e.text&&!t){let s=n.selectionStart;n.value=n.value.slice(0,s)+e.text+n.value.slice(s),n.selectionStart=s,n.selectionEnd=s+e.text.length}let r=D(n,i);$(n,r)}function ye(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.bulletList);ue(n,e)}function be(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.numberedList);ue(n,e)}function we(n){if(!n||n.disabled||n.readOnly)return;b("toggleQuote","Starting"),V(n,"Initial");let e=M(C.quote),t=U(n,i=>he(i,e),{prefix:e.prefix});pe(t),$(n,t),V(n,"Final")}function X(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.taskList),t=U(n,i=>he(i,e),{prefix:e.prefix});$(n,t)}function Y(n,e=1,t=!1){if(!n||n.disabled||n.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${n.selectionStart}-${n.selectionEnd}`);let i=`header${e===1?"1":e}`,o=M(C[i]||C.header1);b("insertHeader",`Style prefix: "${o.prefix}"`);let r=n.value,s=n.selectionStart,a=n.selectionEnd,c=s;for(;c>0&&r[c-1]!==` `;)c--;let d=a;for(;d{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):h>0?(b("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=o.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=o.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:o.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let $=Math.max(y-u,x);return b("insertHeader",` - Removing header, adjusting by -${u}`),{start:$,end:y===w?$:Math.max(w-u,x)}}else if(u>0){let $=o.prefix.length-u;return b("insertHeader",` - Replacing header, adjusting by ${$}`),{start:y+$,end:w+$}}else return b("insertHeader",` - Adding header, adjusting by +${o.prefix.length}`),{start:y+o.prefix.length,end:w+o.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),I(n,f)}function we(n){X(n,1,!0)}function xe(n){X(n,2,!0)}function ke(n){X(n,3,!0)}function Le(n){return rt(n)}var q=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",i=>{i.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=i=>{i.preventDefault();let o=e.actionId||e.name;this.editor.performAction(o,i)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let i=this.createViewModeDropdown(e),o=e.getBoundingClientRect();i.style.position="absolute",i.style.top=`${o.bottom+5}px`,i.style.left=`${o.left}px`,document.body.appendChild(i),this.handleDocumentClick=r=>{!i.contains(r.target)&&!e.contains(r.target)&&(i.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let i=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],o=this.editor.container.dataset.mode||"normal";return i.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===o){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Le)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([i,o])=>{if(i==="viewMode")return;let r=!1;switch(i){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}o.classList.toggle("active",r),o.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:i,offset:o,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:i,offset:o,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` +`;)d++;let l=r.slice(c,d);b("insertHeader",`Current line (before): "${l}"`);let p=l.match(/^(#{1,6})\s*/),u=p?p[1].length:0,m=p?p[0].length:0;b("insertHeader","Existing header check:"),b("insertHeader",` - Match: ${p?`"${p[0]}"`:"none"}`),b("insertHeader",` - Existing level: ${u}`),b("insertHeader",` - Existing prefix length: ${m}`),b("insertHeader",` - Target level: ${e}`);let g=t&&u===e;b("insertHeader",`Should toggle OFF: ${g} (toggle=${t}, existingLevel=${u}, level=${e})`);let f=U(n,v=>{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):u>0?(b("insertHeader",`ACTION: Replacing H${u} with H${e}`),x=o.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=o.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:o.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let I=Math.max(y-m,x);return b("insertHeader",` - Removing header, adjusting by -${m}`),{start:I,end:y===w?I:Math.max(w-m,x)}}else if(m>0){let I=o.prefix.length-m;return b("insertHeader",` - Replacing header, adjusting by ${I}`),{start:y+I,end:w+I}}else return b("insertHeader",` - Adding header, adjusting by +${o.prefix.length}`),{start:y+o.prefix.length,end:w+o.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),$(n,f)}function xe(n){Y(n,1,!0)}function ke(n){Y(n,2,!0)}function Le(n){Y(n,3,!0)}function Se(n){return st(n)}var W=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",i=>{i.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=i=>{i.preventDefault();let o=e.actionId||e.name;this.editor.performAction(o,i)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let i=this.createViewModeDropdown(e),o=e.getBoundingClientRect();i.style.position="absolute",i.style.top=`${o.bottom+5}px`,i.style.left=`${o.left}px`,document.body.appendChild(i),this.handleDocumentClick=r=>{!i.contains(r.target)&&!e.contains(r.target)&&(i.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let i=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],o=this.editor.container.dataset.mode||"normal";return i.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===o){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Se)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([i,o])=>{if(i==="viewMode")return;let r=!1;switch(i){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}o.classList.toggle("active",r),o.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var K=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:i,offset:o,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:i,offset:o,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` @@ -890,24 +890,24 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! - `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,i=this.findLinkAtPosition(t,e);i?(!this.currentLink||this.currentLink.url!==i.url||this.currentLink.index!==i.index)&&this.show(i):this.scheduleHide()}findLinkAtPosition(e,t){let i=/\[([^\]]+)\]\(([^)]+)\)/g,o,r=0;for(;(o=i.exec(e))!==null;){let s=o.index,a=o.index+o[0].length;if(t>=s&&t<=a)return{text:o[1],url:o[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let i=t.getBoundingClientRect();if(!(i.width===0||i.height===0))try{let{x:o,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${o}px`,top:`${r}px`,position:"absolute"})}catch(o){console.warn("Floating UI positioning failed:",o);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Te=` + `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,i=this.findLinkAtPosition(t,e);i?(!this.currentLink||this.currentLink.url!==i.url||this.currentLink.index!==i.index)&&this.show(i):this.scheduleHide()}findLinkAtPosition(e,t){let i=/\[([^\]]+)\]\(([^)]+)\)/g,o,r=0;for(;(o=i.exec(e))!==null;){let s=o.index,a=o.index+o[0].length;if(t>=s&&t<=a)return{text:o[1],url:o[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let i=t.getBoundingClientRect();if(!(i.width===0||i.height===0))try{let{x:o,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${o}px`,top:`${r}px`,position:"absolute"})}catch(o){console.warn("Floating UI positioning failed:",o);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var _e=` -`,Ee=` +`,Ce=` -`,_e=` +`,Te=` -`,Ce=` - `,Ae=` - + `,He=` + +`,Me=` -`,Me=` +`,Ie=` @@ -918,7 +918,7 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! -`,Ie=` +`,Pe=` @@ -926,20 +926,20 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! -`,Pe=` +`,Be=` -`,Be=` +`,ze=` -`,ze=` +`,Oe=` -`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Te,title:"Bold (Ctrl+B)",action:({editor:n})=>{ue(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Ee,title:"Italic (Ctrl+I)",action:({editor:n})=>{me(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:Me,title:"Inline Code",action:({editor:n})=>{fe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:n})=>{ge(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:_e,title:"Heading 1",action:({editor:n})=>{we(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ce,title:"Heading 2",action:({editor:n})=>{xe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Ae,title:"Heading 3",action:({editor:n})=>{ke(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:n})=>{ve(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Ie,title:"Numbered List",action:({editor:n})=>{ye(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:Be,title:"Task List",action:({editor:n})=>{J&&(J(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:n})=>{be(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:ze,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function Oe(n){let e={};return(n||[]).forEach(t=>{if(!t||t.name==="separator")return;let i=t.actionId||t.name;t.action&&(e[i]=t.action)}),e}function Ne(n){let e=n||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function at(n,e){let t=Ne(n),i=Ne(e);if(t===null||i===null)return t!==i;if(t.length!==i.length)return!0;for(let o=0;o{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(m.prototype);return s._init(r,t),r.overTypeInstance=s,m.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++m.instanceCount,this.initialized=!1,m.injectStyles(),m.initGlobalListeners();let i=e.querySelector(".overtype-container"),o=e.querySelector(".overtype-wrapper");i||o?this._recoverFromDOM(i,o):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:i,colors:o,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let i=this.instanceTheme||m.currentTheme||A,o=typeof i=="string"?i:i.name;if(o&&this.container.setAttribute("data-theme",o),this.instanceTheme){let r=typeof this.instanceTheme=="string"?E(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=B(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||m.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let i=typeof this.instanceTheme=="string"?E(this.instanceTheme):this.instanceTheme;if(i&&i.colors){let o=B(i.colors);this.container.style.cssText+=o}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([i,o])=>{i==="className"||i==="class"?this.textarea.className+=" "+o:i==="style"&&typeof o=="object"?Object.assign(this.textarea.style,o):this.textarea.setAttribute(i,o)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new q(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=Oe(N),this.options.toolbarButtons&&Object.assign(this.actionsById,Oe(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,i=this._getCurrentLine(e,t),o=this.container.dataset.mode==="preview",r=S.parse(e,i,this.options.showActiveLineRaw,this.options.codeHighlighter,o);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;t`;var k={bold:{name:"bold",actionId:"toggleBold",icon:_e,title:"Bold (Ctrl+B)",action:({editor:n})=>{me(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Ce,title:"Italic (Ctrl+I)",action:({editor:n})=>{fe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:Ie,title:"Inline Code",action:({editor:n})=>{ge(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:Me,title:"Insert Link",action:({editor:n})=>{ve(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Te,title:"Heading 1",action:({editor:n})=>{xe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:n})=>{ke(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:He,title:"Heading 3",action:({editor:n})=>{Le(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:n})=>{ye(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Pe,title:"Numbered List",action:({editor:n})=>{be(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:ze,title:"Task List",action:({editor:n})=>{X&&(X(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Be,title:"Quote",action:({editor:n})=>{we(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Oe,title:"View mode"}},j=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function Ne(n){let e={};return(n||[]).forEach(t=>{if(!t||t.name==="separator")return;let i=t.actionId||t.name;t.action&&(e[i]=t.action)}),e}function je(n){let e=n||j;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function lt(n,e){let t=je(n),i=je(e);if(t===null||i===null)return t!==i;if(t.length!==i.length)return!0;for(let o=0;o{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(h.prototype);return s._init(r,t),r.overTypeInstance=s,h.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++h.instanceCount,this.initialized=!1,h.injectStyles(),h.initGlobalListeners();let i=e.querySelector(".overtype-container"),o=e.querySelector(".overtype-wrapper");i||o?this._recoverFromDOM(i,o):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new K(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:i,colors:o,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let i=this.instanceTheme||h.currentTheme||A,o=typeof i=="string"?i:i.name;if(o&&this.container.setAttribute("data-theme",o),this.instanceTheme){let r=typeof this.instanceTheme=="string"?_(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=B(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||h.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let i=typeof this.instanceTheme=="string"?_(this.instanceTheme):this.instanceTheme;if(i&&i.colors){let o=B(i.colors);this.container.style.cssText+=o}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([i,o])=>{i==="className"||i==="class"?this.textarea.className+=" "+o:i==="style"&&typeof o=="object"?Object.assign(this.textarea.style,o):this.textarea.setAttribute(i,o)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||j;this.toolbar=new W(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=Ne(j),this.options.toolbarButtons&&Object.assign(this.actionsById,Ne(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,i=this._getCurrentLine(e,t),o=this.container.dataset.mode==="preview",r=S.parse(e,i,this.options.showActiveLineRaw,this.options.codeHighlighter,o);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tp.replace(/^ /,"")).join(` `);document.execCommand?(this.textarea.setSelectionRange(i,o),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=i,this.textarea.selectionEnd=i+l.length)}else if(i!==o){let s=r.substring(0,i),a=r.substring(i,o),c=r.substring(o),l=a.split(` @@ -948,7 +948,7 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! `+t),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}splitListItem(e,t){let i=e.content.substring(t-e.markerEndPos);this.textarea.setSelectionRange(t,e.lineEnd),document.execCommand("delete");let o=S.createNewListItem(e);document.execCommand("insertText",!1,` `+o+i);let r=this.textarea.selectionStart-i.length;this.textarea.setSelectionRange(r,r),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}scheduleNumberedListUpdate(){this.numberUpdateTimeout&&clearTimeout(this.numberUpdateTimeout),this.numberUpdateTimeout=setTimeout(()=>{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,i=S.renumberLists(e);if(i!==e){let o=0,r=e.split(` `),s=i.split(` -`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),i=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(i=i.replace(/.*?<\/span>/g,""),i=i.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),i=i.replace(/\sclass=""/g,"")),i}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var o;let t=(o=this.options)==null?void 0:o.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let i=this.toolbar&&this.options.toolbar&&at(t,this.options.toolbarButtons);this._rebuildActionsMap(),i&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAutoThemeListener(),this.instanceTheme=e,e==="auto"){this._setupAutoThemeListener();let t=Q("auto");this._applyResolvedTheme(t)}else{let t=typeof e=="string"?E(e):e,i=typeof t=="string"?t:t.name;if(i&&this.container.setAttribute("data-theme",i),t&&t.colors){let o=B(t.colors);this.container.style.cssText+=o}this.updatePreview()}return this}_applyResolvedTheme(e){let t=E(e);if(this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t&&t.colors){let i=B(t.colors);this.container.style.cssText+=i}this.updatePreview()}_setupAutoThemeListener(){window.matchMedia&&(this.autoThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.autoThemeListener=e=>{let t=e.matches?"cave":"solar";this._applyResolvedTheme(t)},this.autoThemeMediaQuery.addEventListener?this.autoThemeMediaQuery.addEventListener("change",this.autoThemeListener):this.autoThemeMediaQuery.addListener&&this.autoThemeMediaQuery.addListener(this.autoThemeListener))}_cleanupAutoThemeListener(){this.autoThemeMediaQuery&&this.autoThemeListener&&(this.autoThemeMediaQuery.removeEventListener?this.autoThemeMediaQuery.removeEventListener("change",this.autoThemeListener):this.autoThemeMediaQuery.removeListener&&this.autoThemeMediaQuery.removeListener(this.autoThemeListener),this.autoThemeMediaQuery=null,this.autoThemeListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` +`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),i=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(i=i.replace(/.*?<\/span>/g,""),i=i.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),i=i.replace(/\sclass=""/g,"")),i}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var o;let t=(o=this.options)==null?void 0:o.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let i=this.toolbar&&this.options.toolbar&<(t,this.options.toolbarButtons);this._rebuildActionsMap(),i&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(Z("auto"));else{let t=typeof e=="string"?_(e):e,i=typeof t=="string"?t:t.name;if(i&&this.container.setAttribute("data-theme",i),t&&t.colors){let o=B(t.colors);this.container.style.cssText+=o}this.updatePreview()}return this}_applyTheme(e){let t=_(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=B(t.colors)),this.updatePreview()}_setupAuto(){window.matchMedia&&(h._autoInstances.add(this),h._mq||(h._mq=window.matchMedia("(prefers-color-scheme: dark)"),h._mqListener=e=>{let t=e.matches?"cave":"solar";h._autoInstances.forEach(i=>i._applyTheme(t))},h._mq.addEventListener?h._mq.addEventListener("change",h._mqListener):h._mq.addListener&&h._mq.addListener(h._mqListener)))}_cleanupAuto(){h._autoInstances.delete(this),h._autoInstances.size===0&&h._mq&&(h._mq.removeEventListener?h._mq.removeEventListener("change",h._mqListener):h._mq.removeListener&&h._mq.removeListener(h._mqListener),h._mq=null,h._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` `),i=e.length,o=e.split(/\s+/).filter(l=>l.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(` `),c=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:i,words:o,lines:t.length,line:c,column:d}):this.statsBar.innerHTML=`
    @@ -956,8 +956,8 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! ${i} chars, ${o} words, ${t.length} lines
    Line ${c}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper,o=window.getComputedStyle(e),r=parseFloat(o.paddingTop),s=parseFloat(o.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAutoThemeListener(),this.element.overTypeInstance=null,m.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new m(e,t)}static initFromData(e,t={}){let i=document.querySelectorAll(e);return Array.from(i).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=m._parseDataValue(s.value)}return new m(o,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||m.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=m.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(m.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=m.currentTheme||A,o=R({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),m.stylesInjected=!0}static setTheme(e,t=null){if(m._cleanupGlobalAutoThemeListener(),e==="auto"){m._setupGlobalAutoThemeListener();let i=Q("auto");m._applyGlobalResolvedTheme(i,t)}else{let i=typeof e=="string"?E(e):e;t&&(i=G(i,t)),m.currentTheme=i,m.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(r=>{let s=typeof i=="string"?i:i.name;s&&r.setAttribute("data-theme",s)}),document.querySelectorAll(".overtype-wrapper").forEach(r=>{if(!r.closest(".overtype-container")){let a=typeof i=="string"?i:i.name;a&&r.setAttribute("data-theme",a)}let s=r._instance;s&&s.updatePreview()});let o=typeof i=="string"?i:i.name;document.querySelectorAll("overtype-editor").forEach(r=>{o&&typeof r.setAttribute=="function"&&r.setAttribute("theme",o),typeof r.refreshTheme=="function"&&r.refreshTheme()})}}static _applyGlobalResolvedTheme(e,t=null){let i=E(e);t&&(i=G(i,t)),m.currentTheme=i,m.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(o=>{o.setAttribute("data-theme","auto"),o.setAttribute("data-resolved-theme",e)}),document.querySelectorAll(".overtype-wrapper").forEach(o=>{o.closest(".overtype-container")||(o.setAttribute("data-theme","auto"),o.setAttribute("data-resolved-theme",e));let r=o._instance;r&&r.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(o=>{typeof o.setAttribute=="function"&&(o.setAttribute("theme","auto"),o.setAttribute("data-resolved-theme",e)),typeof o.refreshTheme=="function"&&o.refreshTheme()})}static _setupGlobalAutoThemeListener(){window.matchMedia&&(m.autoThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),m.autoThemeListener=e=>{let t=e.matches?"cave":"solar";m._applyGlobalResolvedTheme(t)},m.autoThemeMediaQuery.addEventListener?m.autoThemeMediaQuery.addEventListener("change",m.autoThemeListener):m.autoThemeMediaQuery.addListener&&m.autoThemeMediaQuery.addListener(m.autoThemeListener))}static _cleanupGlobalAutoThemeListener(){m.autoThemeMediaQuery&&m.autoThemeListener&&(m.autoThemeMediaQuery.removeEventListener?m.autoThemeMediaQuery.removeEventListener("change",m.autoThemeListener):m.autoThemeMediaQuery.removeListener&&m.autoThemeMediaQuery.removeListener(m.autoThemeListener),m.autoThemeMediaQuery=null,m.autoThemeListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static initGlobalListeners(){m.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let i=t.closest(".overtype-wrapper"),o=i==null?void 0:i._instance;o&&(o.options.showStats&&o.statsBar&&o._updateStats(),clearTimeout(o._selectionTimeout),o._selectionTimeout=setTimeout(()=>{o.updatePreview()},50))}}),m.globalListenersInitialized=!0)}};T(m,"instances",new WeakMap),T(m,"stylesInjected",!1),T(m,"globalListenersInitialized",!1),T(m,"instanceCount",0),T(m,"autoThemeMediaQuery",null),T(m,"autoThemeListener",null);var P=m;P.MarkdownParser=S;P.ShortcutsManager=z;P.themes={solar:A,cave:E("cave")};P.getTheme=E;P.currentTheme=A;var je=P;var Re="overtype-webcomponent-container",lt="Start typing...",ct=["value","theme","toolbar","height","min-height","max-height","placeholder","font-size","line-height","padding","auto-resize","autofocus","show-stats","smart-lists","readonly"],K=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._editor=null,this._initialized=!1,this._pendingOptions={},this._styleVersion=0,this._baseStyleElement=null,this._selectionChangeHandler=null,this._isConnected=!1,this._handleChange=this._handleChange.bind(this),this._handleKeydown=this._handleKeydown.bind(this)}_decodeValue(e){return typeof e!="string"?"":e.replace(/\\r/g,"\r").replace(/\\n/g,` -`).replace(/\\t/g," ")}static get observedAttributes(){return ct}connectedCallback(){this._isConnected=!0,this._initializeEditor()}disconnectedCallback(){this._isConnected=!1,this._cleanup()}attributeChangedCallback(e,t,i){if(t!==i&&!this._silentUpdate){if(!this._initialized){this._pendingOptions[e]=i;return}this._updateOption(e,i)}}_initializeEditor(){if(!(this._initialized||!this._isConnected))try{let e=document.createElement("div");e.className=Re;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");t&&(e.style.height=t),i&&(e.style.minHeight=i),o&&(e.style.maxHeight=o),this._injectStyles(),this.shadowRoot.appendChild(e);let r=this._getOptionsFromAttributes(),s=new je(e,r);this._editor=s[0],this._initialized=!0,this._editor&&this._editor.textarea&&(this._editor.textarea.addEventListener("scroll",()=>{this._editor&&this._editor.preview&&this._editor.textarea&&(this._editor.preview.scrollTop=this._editor.textarea.scrollTop,this._editor.preview.scrollLeft=this._editor.textarea.scrollLeft)}),this._editor.textarea.addEventListener("input",a=>{this._editor&&this._editor.handleInput&&this._editor.handleInput(a)}),this._editor.textarea.addEventListener("keydown",a=>{this._editor&&this._editor.handleKeydown&&this._editor.handleKeydown(a)}),this._selectionChangeHandler=()=>{if(document.activeElement===this){let a=this.shadowRoot.activeElement;a&&a===this._editor.textarea&&(this._editor.options.showStats&&this._editor.statsBar&&this._editor._updateStats(),this._editor.linkTooltip&&this._editor.linkTooltip.checkCursorPosition&&this._editor.linkTooltip.checkCursorPosition())}},document.addEventListener("selectionchange",this._selectionChangeHandler)),this._applyPendingOptions(),this._dispatchEvent("ready",{editor:this._editor})}catch(e){let t=e&&e.message?e.message:String(e);console.warn("OverType Web Component initialization failed:",t),this._dispatchEvent("error",{error:{message:t}})}}_injectStyles(){let e=document.createElement("style"),t=this.getAttribute("theme")||"solar",i=E(t),o=this._getOptionsFromAttributes(),r=R({...o,theme:i}),s=` + `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper,o=window.getComputedStyle(e),r=parseFloat(o.paddingTop),s=parseFloat(o.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,h.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new h(e,t)}static initFromData(e,t={}){let i=document.querySelectorAll(e);return Array.from(i).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=h._parseDataValue(s.value)}return new h(o,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||h.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=h.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(h.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=h.currentTheme||A,o=R({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),h.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let i=document.querySelectorAll(".overtype-container"),o=document.querySelectorAll(".overtype-wrapper");i.forEach(r=>{t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)}),o.forEach(r=>{var s;r.closest(".overtype-container")||(t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)),(s=r._instance)==null||s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{var s,a,c,d;t?((s=r.setAttribute)==null||s.call(r,"theme","auto"),(a=r.setAttribute)==null||a.call(r,"data-resolved-theme",e)):(c=r.setAttribute)==null||c.call(r,"theme",e),(d=r.refreshTheme)==null||d.call(r)})}static setTheme(e,t=null){if(h._cleanupGlobalAuto(),e==="auto")h._setupGlobalAuto(),h._applyGlobalTheme(Z("auto"),t,!0);else{let i=typeof e=="string"?_(e):e;t&&(i=J(i,t)),h.currentTheme=i,h.injectStyles(!0);let o=i.name||e;o&&h._updateThemeAttrs(o)}}static _applyGlobalTheme(e,t=null,i=!1){let o=_(e);t&&(o=J(o,t)),h.currentTheme=o,h.injectStyles(!0),h._updateThemeAttrs(e,i)}static _setupGlobalAuto(){!window.matchMedia||h._globalAutoMq||(h._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),h._globalAutoListener=e=>{h._applyGlobalTheme(e.matches?"cave":"solar",null,!0)},h._globalAutoMq.addEventListener?h._globalAutoMq.addEventListener("change",h._globalAutoListener):h._globalAutoMq.addListener&&h._globalAutoMq.addListener(h._globalAutoListener))}static _cleanupGlobalAuto(){h._globalAutoMq&&h._globalAutoListener&&(h._globalAutoMq.removeEventListener?h._globalAutoMq.removeEventListener("change",h._globalAutoListener):h._globalAutoMq.removeListener&&h._globalAutoMq.removeListener(h._globalAutoListener),h._globalAutoMq=null,h._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static initGlobalListeners(){h.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let i=t.closest(".overtype-wrapper"),o=i==null?void 0:i._instance;o&&(o.options.showStats&&o.statsBar&&o._updateStats(),clearTimeout(o._selectionTimeout),o._selectionTimeout=setTimeout(()=>{o.updatePreview()},50))}}),h.globalListenersInitialized=!0)}};E(h,"instances",new WeakMap),E(h,"stylesInjected",!1),E(h,"globalListenersInitialized",!1),E(h,"instanceCount",0),E(h,"_mq",null),E(h,"_mqListener",null),E(h,"_autoInstances",new Set),E(h,"_globalAutoMq",null),E(h,"_globalAutoListener",null);var P=h;P.MarkdownParser=S;P.ShortcutsManager=z;P.themes={solar:A,cave:_("cave")};P.getTheme=_;P.currentTheme=A;var Fe=P;var Re="overtype-webcomponent-container",ct="Start typing...",pt=["value","theme","toolbar","height","min-height","max-height","placeholder","font-size","line-height","padding","auto-resize","autofocus","show-stats","smart-lists","readonly"],G=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._editor=null,this._initialized=!1,this._pendingOptions={},this._styleVersion=0,this._baseStyleElement=null,this._selectionChangeHandler=null,this._isConnected=!1,this._handleChange=this._handleChange.bind(this),this._handleKeydown=this._handleKeydown.bind(this)}_decodeValue(e){return typeof e!="string"?"":e.replace(/\\r/g,"\r").replace(/\\n/g,` +`).replace(/\\t/g," ")}static get observedAttributes(){return pt}connectedCallback(){this._isConnected=!0,this._initializeEditor()}disconnectedCallback(){this._isConnected=!1,this._cleanup()}attributeChangedCallback(e,t,i){if(t!==i&&!this._silentUpdate){if(!this._initialized){this._pendingOptions[e]=i;return}this._updateOption(e,i)}}_initializeEditor(){if(!(this._initialized||!this._isConnected))try{let e=document.createElement("div");e.className=Re;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");t&&(e.style.height=t),i&&(e.style.minHeight=i),o&&(e.style.maxHeight=o),this._injectStyles(),this.shadowRoot.appendChild(e);let r=this._getOptionsFromAttributes(),s=new Fe(e,r);this._editor=s[0],this._initialized=!0,this._editor&&this._editor.textarea&&(this._editor.textarea.addEventListener("scroll",()=>{this._editor&&this._editor.preview&&this._editor.textarea&&(this._editor.preview.scrollTop=this._editor.textarea.scrollTop,this._editor.preview.scrollLeft=this._editor.textarea.scrollLeft)}),this._editor.textarea.addEventListener("input",a=>{this._editor&&this._editor.handleInput&&this._editor.handleInput(a)}),this._editor.textarea.addEventListener("keydown",a=>{this._editor&&this._editor.handleKeydown&&this._editor.handleKeydown(a)}),this._selectionChangeHandler=()=>{if(document.activeElement===this){let a=this.shadowRoot.activeElement;a&&a===this._editor.textarea&&(this._editor.options.showStats&&this._editor.statsBar&&this._editor._updateStats(),this._editor.linkTooltip&&this._editor.linkTooltip.checkCursorPosition&&this._editor.linkTooltip.checkCursorPosition())}},document.addEventListener("selectionchange",this._selectionChangeHandler)),this._applyPendingOptions(),this._dispatchEvent("ready",{editor:this._editor})}catch(e){let t=e&&e.message?e.message:String(e);console.warn("OverType Web Component initialization failed:",t),this._dispatchEvent("error",{error:{message:t}})}}_injectStyles(){let e=document.createElement("style"),t=this.getAttribute("theme")||"solar",i=_(t),o=this._getOptionsFromAttributes(),r=R({...o,theme:i}),s=` /* Web Component Host Styles */ :host { display: block; @@ -979,9 +979,9 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! } `;this._styleVersion+=1;let a=` /* overtype-webcomponent styles v${this._styleVersion} */ -`;e.textContent=a+r+s,this._baseStyleElement=e,this.shadowRoot.appendChild(e)}_getOptionsFromAttributes(){let e={value:this.getAttribute("value")!==null?this._decodeValue(this.getAttribute("value")):(this.textContent||"").trim(),placeholder:this.getAttribute("placeholder")||lt,toolbar:this.hasAttribute("toolbar"),autofocus:this.hasAttribute("autofocus"),autoResize:this.hasAttribute("auto-resize"),showStats:this.hasAttribute("show-stats"),smartLists:!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false",onChange:this._handleChange,onKeydown:this._handleKeydown},t=this.getAttribute("font-size");t&&(e.fontSize=t);let i=this.getAttribute("line-height");i&&(e.lineHeight=parseFloat(i)||1.6);let o=this.getAttribute("padding");o&&(e.padding=o);let r=this.getAttribute("min-height");r&&(e.minHeight=r);let s=this.getAttribute("max-height");return s&&(e.maxHeight=s),e}_applyPendingOptions(){for(let[e,t]of Object.entries(this._pendingOptions))this._updateOption(e,t);this._pendingOptions={}}_updateOption(e,t){if(this._editor)switch(e){case"value":{let i=this._decodeValue(t);this._editor.getValue()!==i&&this._editor.setValue(i||"")}break;case"theme":this._reinjectStyles(),this._editor&&this._editor.setTheme&&this._editor.setTheme(t||"solar");break;case"placeholder":this._editor.textarea&&(this._editor.textarea.placeholder=t||"");break;case"readonly":this._editor.textarea&&(this._editor.textarea.readOnly=this.hasAttribute("readonly"));break;case"height":case"min-height":case"max-height":this._updateContainerHeight();break;case"toolbar":if(!!this.hasAttribute("toolbar")==!!this._editor.options.toolbar)return;this._reinitializeEditor();break;case"auto-resize":if(!!this.hasAttribute("auto-resize")==!!this._editor.options.autoResize)return;this._reinitializeEditor();break;case"show-stats":if(!!this.hasAttribute("show-stats")==!!this._editor.options.showStats)return;this._reinitializeEditor();break;case"font-size":{this._updateFontSize(t)&&this._reinjectStyles();break}case"line-height":{this._updateLineHeight(t)&&this._reinjectStyles();break}case"padding":this._reinjectStyles();break;case"smart-lists":{let i=!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false";if(!!this._editor.options.smartLists==!!i)return;this._reinitializeEditor();break}}}_updateContainerHeight(){let e=this.shadowRoot.querySelector(`.${Re}`);if(!e)return;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");e.style.height=t||"",e.style.minHeight=i||"",e.style.maxHeight=o||""}_updateFontSize(e){return this._editor&&this._editor.wrapper?(this._editor.options.fontSize=e||"",this._editor.wrapper.style.setProperty("--instance-font-size",this._editor.options.fontSize),this._editor.updatePreview(),!0):!1}_updateLineHeight(e){if(this._editor&&this._editor.wrapper){let t=parseFloat(e),i=Number.isFinite(t)?t:this._editor.options.lineHeight;return this._editor.options.lineHeight=i,this._editor.wrapper.style.setProperty("--instance-line-height",String(i)),this._editor.updatePreview(),!0}return!1}_reinjectStyles(){this._baseStyleElement&&this._baseStyleElement.parentNode&&this._baseStyleElement.remove(),this._injectStyles()}_reinitializeEditor(){let e=this._editor?this._editor.getValue():"";this._cleanup(),this._initialized=!1,this.shadowRoot.innerHTML="",e&&!this.getAttribute("value")&&this.setAttribute("value",e),this._initializeEditor()}_handleChange(e){this._updateValueAttribute(e),!(!this._initialized||!this._editor)&&this._dispatchEvent("change",{value:e,editor:this._editor})}_handleKeydown(e){this._dispatchEvent("keydown",{event:e,editor:this._editor})}_updateValueAttribute(e){this.getAttribute("value")!==e&&(this._silentUpdate=!0,this.setAttribute("value",e),this._silentUpdate=!1)}_dispatchEvent(e,t={}){let i=new CustomEvent(e,{detail:t,bubbles:!0,composed:!0});this.dispatchEvent(i)}_cleanup(){this._selectionChangeHandler&&(document.removeEventListener("selectionchange",this._selectionChangeHandler),this._selectionChangeHandler=null),this._editor&&typeof this._editor.destroy=="function"&&this._editor.destroy(),this._editor=null,this._initialized=!1,this.shadowRoot&&(this.shadowRoot.innerHTML="")}refreshTheme(){this._initialized&&this._reinjectStyles()}getValue(){return this._editor?this._editor.getValue():this.getAttribute("value")||""}setValue(e){this._editor?this._editor.setValue(e):this.setAttribute("value",e)}getHTML(){return this._editor?this._editor.getRenderedHTML(!1):""}insertText(e){!this._editor||typeof e!="string"||this._editor.insertText(e)}focus(){this._editor&&this._editor.textarea&&this._editor.textarea.focus()}blur(){this._editor&&this._editor.textarea&&this._editor.textarea.blur()}getStats(){if(!this._editor||!this._editor.textarea)return null;let e=this._editor.textarea.value,t=e.split(` +`;e.textContent=a+r+s,this._baseStyleElement=e,this.shadowRoot.appendChild(e)}_getOptionsFromAttributes(){let e={value:this.getAttribute("value")!==null?this._decodeValue(this.getAttribute("value")):(this.textContent||"").trim(),placeholder:this.getAttribute("placeholder")||ct,toolbar:this.hasAttribute("toolbar"),autofocus:this.hasAttribute("autofocus"),autoResize:this.hasAttribute("auto-resize"),showStats:this.hasAttribute("show-stats"),smartLists:!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false",onChange:this._handleChange,onKeydown:this._handleKeydown},t=this.getAttribute("font-size");t&&(e.fontSize=t);let i=this.getAttribute("line-height");i&&(e.lineHeight=parseFloat(i)||1.6);let o=this.getAttribute("padding");o&&(e.padding=o);let r=this.getAttribute("min-height");r&&(e.minHeight=r);let s=this.getAttribute("max-height");return s&&(e.maxHeight=s),e}_applyPendingOptions(){for(let[e,t]of Object.entries(this._pendingOptions))this._updateOption(e,t);this._pendingOptions={}}_updateOption(e,t){if(this._editor)switch(e){case"value":{let i=this._decodeValue(t);this._editor.getValue()!==i&&this._editor.setValue(i||"")}break;case"theme":this._reinjectStyles(),this._editor&&this._editor.setTheme&&this._editor.setTheme(t||"solar");break;case"placeholder":this._editor.textarea&&(this._editor.textarea.placeholder=t||"");break;case"readonly":this._editor.textarea&&(this._editor.textarea.readOnly=this.hasAttribute("readonly"));break;case"height":case"min-height":case"max-height":this._updateContainerHeight();break;case"toolbar":if(!!this.hasAttribute("toolbar")==!!this._editor.options.toolbar)return;this._reinitializeEditor();break;case"auto-resize":if(!!this.hasAttribute("auto-resize")==!!this._editor.options.autoResize)return;this._reinitializeEditor();break;case"show-stats":if(!!this.hasAttribute("show-stats")==!!this._editor.options.showStats)return;this._reinitializeEditor();break;case"font-size":{this._updateFontSize(t)&&this._reinjectStyles();break}case"line-height":{this._updateLineHeight(t)&&this._reinjectStyles();break}case"padding":this._reinjectStyles();break;case"smart-lists":{let i=!this.hasAttribute("smart-lists")||this.getAttribute("smart-lists")!=="false";if(!!this._editor.options.smartLists==!!i)return;this._reinitializeEditor();break}}}_updateContainerHeight(){let e=this.shadowRoot.querySelector(`.${Re}`);if(!e)return;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");e.style.height=t||"",e.style.minHeight=i||"",e.style.maxHeight=o||""}_updateFontSize(e){return this._editor&&this._editor.wrapper?(this._editor.options.fontSize=e||"",this._editor.wrapper.style.setProperty("--instance-font-size",this._editor.options.fontSize),this._editor.updatePreview(),!0):!1}_updateLineHeight(e){if(this._editor&&this._editor.wrapper){let t=parseFloat(e),i=Number.isFinite(t)?t:this._editor.options.lineHeight;return this._editor.options.lineHeight=i,this._editor.wrapper.style.setProperty("--instance-line-height",String(i)),this._editor.updatePreview(),!0}return!1}_reinjectStyles(){this._baseStyleElement&&this._baseStyleElement.parentNode&&this._baseStyleElement.remove(),this._injectStyles()}_reinitializeEditor(){let e=this._editor?this._editor.getValue():"";this._cleanup(),this._initialized=!1,this.shadowRoot.innerHTML="",e&&!this.getAttribute("value")&&this.setAttribute("value",e),this._initializeEditor()}_handleChange(e){this._updateValueAttribute(e),!(!this._initialized||!this._editor)&&this._dispatchEvent("change",{value:e,editor:this._editor})}_handleKeydown(e){this._dispatchEvent("keydown",{event:e,editor:this._editor})}_updateValueAttribute(e){this.getAttribute("value")!==e&&(this._silentUpdate=!0,this.setAttribute("value",e),this._silentUpdate=!1)}_dispatchEvent(e,t={}){let i=new CustomEvent(e,{detail:t,bubbles:!0,composed:!0});this.dispatchEvent(i)}_cleanup(){this._selectionChangeHandler&&(document.removeEventListener("selectionchange",this._selectionChangeHandler),this._selectionChangeHandler=null),this._editor&&typeof this._editor.destroy=="function"&&this._editor.destroy(),this._editor=null,this._initialized=!1,this.shadowRoot&&(this.shadowRoot.innerHTML="")}refreshTheme(){this._initialized&&this._reinjectStyles()}getValue(){return this._editor?this._editor.getValue():this.getAttribute("value")||""}setValue(e){this._editor?this._editor.setValue(e):this.setAttribute("value",e)}getHTML(){return this._editor?this._editor.getRenderedHTML(!1):""}insertText(e){!this._editor||typeof e!="string"||this._editor.insertText(e)}focus(){this._editor&&this._editor.textarea&&this._editor.textarea.focus()}blur(){this._editor&&this._editor.textarea&&this._editor.textarea.blur()}getStats(){if(!this._editor||!this._editor.textarea)return null;let e=this._editor.textarea.value,t=e.split(` `),i=e.length,o=e.split(/\s+/).filter(l=>l.length>0).length,r=this._editor.textarea.selectionStart,a=e.substring(0,r).split(` -`),c=a.length,d=a[a.length-1].length+1;return{characters:i,words:o,lines:t.length,line:c,column:d}}isReady(){return this._initialized&&this._editor!==null}getEditor(){return this._editor}};customElements.get("overtype-editor")||customElements.define("overtype-editor",K);var pt=K;return Ke(dt);})(); +`),c=a.length,d=a[a.length-1].length+1;return{characters:i,words:o,lines:t.length,line:c,column:d}}isReady(){return this._initialized&&this._editor!==null}getEditor(){return this._editor}};customElements.get("overtype-editor")||customElements.define("overtype-editor",G);var dt=G;return Ge(ht);})(); /** * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment * @version 1.0.0 diff --git a/dist/overtype.cjs b/dist/overtype.cjs index 97069ea..89c9acf 100644 --- a/dist/overtype.cjs +++ b/dist/overtype.cjs @@ -961,12 +961,14 @@ function getTheme(theme) { } return theme; } +var _mq = null; function resolveAutoTheme(themeName) { - if (themeName !== "auto") { + if (themeName !== "auto") return themeName; + if (!_mq && window.matchMedia) { + _mq = window.matchMedia("(prefers-color-scheme: dark)"); } - const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; - return isDarkMode ? "cave" : "solar"; + return (_mq == null ? void 0 : _mq.matches) ? "cave" : "solar"; } function themeToCSSVars(colors) { const vars = []; @@ -3399,7 +3401,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { - // Listener function for auto theme changes + // Global auto theme listener /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4099,12 +4101,11 @@ var _OverType = class _OverType { * @returns {this} Returns this for chaining */ setTheme(theme) { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.instanceTheme = theme; if (theme === "auto") { - this._setupAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - this._applyResolvedTheme(resolvedTheme); + this._setupAuto(); + this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; @@ -4124,13 +4125,12 @@ var _OverType = class _OverType { * @private * @param {string} themeName - Resolved theme name */ - _applyResolvedTheme(themeName) { + _applyTheme(themeName) { const themeObj = getTheme(themeName); this.container.setAttribute("data-theme", "auto"); this.container.setAttribute("data-resolved-theme", themeName); - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4138,33 +4138,37 @@ var _OverType = class _OverType { * Setup auto theme listener for instance * @private */ - _setupAutoThemeListener() { + _setupAuto() { if (!window.matchMedia) return; - this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - this.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - this._applyResolvedTheme(resolvedTheme); - }; - if (this.autoThemeMediaQuery.addEventListener) { - this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.addListener) { - this.autoThemeMediaQuery.addListener(this.autoThemeListener); + _OverType._autoInstances.add(this); + if (!_OverType._mq) { + _OverType._mq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._mqListener = (e) => { + const theme = e.matches ? "cave" : "solar"; + _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); + }; + if (_OverType._mq.addEventListener) { + _OverType._mq.addEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.addListener) { + _OverType._mq.addListener(_OverType._mqListener); + } } } /** * Clean up auto theme listener for instance * @private */ - _cleanupAutoThemeListener() { - if (this.autoThemeMediaQuery && this.autoThemeListener) { - if (this.autoThemeMediaQuery.removeEventListener) { - this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.removeListener) { - this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + _cleanupAuto() { + _OverType._autoInstances.delete(this); + if (_OverType._autoInstances.size === 0 && _OverType._mq) { + if (_OverType._mq.removeEventListener) { + _OverType._mq.removeEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.removeListener) { + _OverType._mq.removeListener(_OverType._mqListener); } - this.autoThemeMediaQuery = null; - this.autoThemeListener = null; + _OverType._mq = null; + _OverType._mqListener = null; } } /** @@ -4319,7 +4323,7 @@ var _OverType = class _OverType { * Destroy the editor instance */ destroy() { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4419,17 +4423,54 @@ var _OverType = class _OverType { document.head.appendChild(styleEl); _OverType.stylesInjected = true; } + /** + * Helper to update DOM elements with theme attributes + * @private + */ + static _updateThemeAttrs(themeName, isAuto = false) { + const containers = document.querySelectorAll(".overtype-container"); + const wrappers = document.querySelectorAll(".overtype-wrapper"); + containers.forEach((el) => { + if (isAuto) { + el.setAttribute("data-theme", "auto"); + el.setAttribute("data-resolved-theme", themeName); + } else { + el.setAttribute("data-theme", themeName); + } + }); + wrappers.forEach((wrapper) => { + var _a; + if (!wrapper.closest(".overtype-container")) { + if (isAuto) { + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); + } else { + wrapper.setAttribute("data-theme", themeName); + } + } + (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + }); + document.querySelectorAll("overtype-editor").forEach((wc) => { + var _a, _b, _c, _d; + if (isAuto) { + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); + } else { + (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); + } + (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + }); + } /** * Set global theme for all OverType instances * @param {string|Object} theme - Theme name or custom theme object * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - _OverType._cleanupGlobalAutoThemeListener(); + _OverType._cleanupGlobalAuto(); if (theme === "auto") { - _OverType._setupGlobalAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + _OverType._setupGlobalAuto(); + _OverType._applyGlobalTheme(resolveAutoTheme("auto"), customColors, true); } else { let themeObj = typeof theme === "string" ? getTheme(theme) : theme; if (customColors) { @@ -4437,33 +4478,10 @@ var _OverType = class _OverType { } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + const themeName = themeObj.name || theme; + if (themeName) { + _OverType._updateThemeAttrs(themeName); + } } } /** @@ -4471,69 +4489,47 @@ var _OverType = class _OverType { * @private * @param {string} themeName - Resolved theme name * @param {Object} customColors - Optional color overrides + * @param {boolean} isAuto - Whether this is an auto theme */ - static _applyGlobalResolvedTheme(themeName, customColors = null) { + static _applyGlobalTheme(themeName, customColors = null, isAuto = false) { let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - container.setAttribute("data-theme", "auto"); - container.setAttribute("data-resolved-theme", themeName); - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", "auto"); - webComponent.setAttribute("data-resolved-theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + _OverType._updateThemeAttrs(themeName, isAuto); } /** * Setup global auto theme listener * @private */ - static _setupGlobalAutoThemeListener() { - if (!window.matchMedia) + static _setupGlobalAuto() { + if (!window.matchMedia || _OverType._globalAutoMq) return; - _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - _OverType.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - _OverType._applyGlobalResolvedTheme(resolvedTheme); + _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._globalAutoListener = (e) => { + _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType.autoThemeMediaQuery.addEventListener) { - _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.addListener) { - _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + if (_OverType._globalAutoMq.addEventListener) { + _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.addListener) { + _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); } } /** * Clean up global auto theme listener * @private */ - static _cleanupGlobalAutoThemeListener() { - if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { - if (_OverType.autoThemeMediaQuery.removeEventListener) { - _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.removeListener) { - _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + static _cleanupGlobalAuto() { + if (_OverType._globalAutoMq && _OverType._globalAutoListener) { + if (_OverType._globalAutoMq.removeEventListener) { + _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.removeListener) { + _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); } - _OverType.autoThemeMediaQuery = null; - _OverType.autoThemeListener = null; + _OverType._globalAutoMq = null; + _OverType._globalAutoListener = null; } } /** @@ -4637,9 +4633,15 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); -__publicField(_OverType, "autoThemeMediaQuery", null); -// Media query for auto theme switching -__publicField(_OverType, "autoThemeListener", null); +__publicField(_OverType, "_mq", null); +// Shared media query for auto theme +__publicField(_OverType, "_mqListener", null); +// Shared listener +__publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); +// Track auto-themed instances +__publicField(_OverType, "_globalAutoMq", null); +// Global auto theme media query +__publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype.esm.js b/dist/overtype.esm.js index 9bb7d1a..7e61504 100644 --- a/dist/overtype.esm.js +++ b/dist/overtype.esm.js @@ -935,12 +935,14 @@ function getTheme(theme) { } return theme; } +var _mq = null; function resolveAutoTheme(themeName) { - if (themeName !== "auto") { + if (themeName !== "auto") return themeName; + if (!_mq && window.matchMedia) { + _mq = window.matchMedia("(prefers-color-scheme: dark)"); } - const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; - return isDarkMode ? "cave" : "solar"; + return (_mq == null ? void 0 : _mq.matches) ? "cave" : "solar"; } function themeToCSSVars(colors) { const vars = []; @@ -3373,7 +3375,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { - // Listener function for auto theme changes + // Global auto theme listener /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4073,12 +4075,11 @@ var _OverType = class _OverType { * @returns {this} Returns this for chaining */ setTheme(theme) { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.instanceTheme = theme; if (theme === "auto") { - this._setupAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - this._applyResolvedTheme(resolvedTheme); + this._setupAuto(); + this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; @@ -4098,13 +4099,12 @@ var _OverType = class _OverType { * @private * @param {string} themeName - Resolved theme name */ - _applyResolvedTheme(themeName) { + _applyTheme(themeName) { const themeObj = getTheme(themeName); this.container.setAttribute("data-theme", "auto"); this.container.setAttribute("data-resolved-theme", themeName); - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4112,33 +4112,37 @@ var _OverType = class _OverType { * Setup auto theme listener for instance * @private */ - _setupAutoThemeListener() { + _setupAuto() { if (!window.matchMedia) return; - this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - this.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - this._applyResolvedTheme(resolvedTheme); - }; - if (this.autoThemeMediaQuery.addEventListener) { - this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.addListener) { - this.autoThemeMediaQuery.addListener(this.autoThemeListener); + _OverType._autoInstances.add(this); + if (!_OverType._mq) { + _OverType._mq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._mqListener = (e) => { + const theme = e.matches ? "cave" : "solar"; + _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); + }; + if (_OverType._mq.addEventListener) { + _OverType._mq.addEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.addListener) { + _OverType._mq.addListener(_OverType._mqListener); + } } } /** * Clean up auto theme listener for instance * @private */ - _cleanupAutoThemeListener() { - if (this.autoThemeMediaQuery && this.autoThemeListener) { - if (this.autoThemeMediaQuery.removeEventListener) { - this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.removeListener) { - this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + _cleanupAuto() { + _OverType._autoInstances.delete(this); + if (_OverType._autoInstances.size === 0 && _OverType._mq) { + if (_OverType._mq.removeEventListener) { + _OverType._mq.removeEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.removeListener) { + _OverType._mq.removeListener(_OverType._mqListener); } - this.autoThemeMediaQuery = null; - this.autoThemeListener = null; + _OverType._mq = null; + _OverType._mqListener = null; } } /** @@ -4293,7 +4297,7 @@ var _OverType = class _OverType { * Destroy the editor instance */ destroy() { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4393,17 +4397,54 @@ var _OverType = class _OverType { document.head.appendChild(styleEl); _OverType.stylesInjected = true; } + /** + * Helper to update DOM elements with theme attributes + * @private + */ + static _updateThemeAttrs(themeName, isAuto = false) { + const containers = document.querySelectorAll(".overtype-container"); + const wrappers = document.querySelectorAll(".overtype-wrapper"); + containers.forEach((el) => { + if (isAuto) { + el.setAttribute("data-theme", "auto"); + el.setAttribute("data-resolved-theme", themeName); + } else { + el.setAttribute("data-theme", themeName); + } + }); + wrappers.forEach((wrapper) => { + var _a; + if (!wrapper.closest(".overtype-container")) { + if (isAuto) { + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); + } else { + wrapper.setAttribute("data-theme", themeName); + } + } + (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + }); + document.querySelectorAll("overtype-editor").forEach((wc) => { + var _a, _b, _c, _d; + if (isAuto) { + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); + } else { + (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); + } + (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + }); + } /** * Set global theme for all OverType instances * @param {string|Object} theme - Theme name or custom theme object * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - _OverType._cleanupGlobalAutoThemeListener(); + _OverType._cleanupGlobalAuto(); if (theme === "auto") { - _OverType._setupGlobalAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + _OverType._setupGlobalAuto(); + _OverType._applyGlobalTheme(resolveAutoTheme("auto"), customColors, true); } else { let themeObj = typeof theme === "string" ? getTheme(theme) : theme; if (customColors) { @@ -4411,33 +4452,10 @@ var _OverType = class _OverType { } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + const themeName = themeObj.name || theme; + if (themeName) { + _OverType._updateThemeAttrs(themeName); + } } } /** @@ -4445,69 +4463,47 @@ var _OverType = class _OverType { * @private * @param {string} themeName - Resolved theme name * @param {Object} customColors - Optional color overrides + * @param {boolean} isAuto - Whether this is an auto theme */ - static _applyGlobalResolvedTheme(themeName, customColors = null) { + static _applyGlobalTheme(themeName, customColors = null, isAuto = false) { let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - container.setAttribute("data-theme", "auto"); - container.setAttribute("data-resolved-theme", themeName); - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", "auto"); - webComponent.setAttribute("data-resolved-theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + _OverType._updateThemeAttrs(themeName, isAuto); } /** * Setup global auto theme listener * @private */ - static _setupGlobalAutoThemeListener() { - if (!window.matchMedia) + static _setupGlobalAuto() { + if (!window.matchMedia || _OverType._globalAutoMq) return; - _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - _OverType.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - _OverType._applyGlobalResolvedTheme(resolvedTheme); + _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._globalAutoListener = (e) => { + _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType.autoThemeMediaQuery.addEventListener) { - _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.addListener) { - _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + if (_OverType._globalAutoMq.addEventListener) { + _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.addListener) { + _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); } } /** * Clean up global auto theme listener * @private */ - static _cleanupGlobalAutoThemeListener() { - if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { - if (_OverType.autoThemeMediaQuery.removeEventListener) { - _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.removeListener) { - _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + static _cleanupGlobalAuto() { + if (_OverType._globalAutoMq && _OverType._globalAutoListener) { + if (_OverType._globalAutoMq.removeEventListener) { + _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.removeListener) { + _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); } - _OverType.autoThemeMediaQuery = null; - _OverType.autoThemeListener = null; + _OverType._globalAutoMq = null; + _OverType._globalAutoListener = null; } } /** @@ -4611,9 +4607,15 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); -__publicField(_OverType, "autoThemeMediaQuery", null); -// Media query for auto theme switching -__publicField(_OverType, "autoThemeListener", null); +__publicField(_OverType, "_mq", null); +// Shared media query for auto theme +__publicField(_OverType, "_mqListener", null); +// Shared listener +__publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); +// Track auto-themed instances +__publicField(_OverType, "_globalAutoMq", null); +// Global auto theme media query +__publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype.esm.js.map b/dist/overtype.esm.js.map index b669962..44e257b 100644 --- a/dist/overtype.esm.js.map +++ b/dist/overtype.esm.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js", "../src/overtype.js"], - "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `[${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') {\n return themeName;\n }\n\n // Check for system dark mode preference\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static autoThemeMediaQuery = null; // Media query for auto theme switching\n static autoThemeListener = null; // Listener function for auto theme changes\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Clean up existing auto theme listener if any\n      this._cleanupAutoThemeListener();\n\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Handle auto theme\n      if (theme === 'auto') {\n        this._setupAutoThemeListener();\n        // Apply the initial resolved theme\n        const resolvedTheme = resolveAutoTheme('auto');\n        this._applyResolvedTheme(resolvedTheme);\n      } else {\n        // Get theme object for non-auto themes\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n        // Update container theme attribute\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        // Apply CSS variables to container for instance override\n        if (themeObj && themeObj.colors) {\n          const cssVars = themeToCSSVars(themeObj.colors);\n          this.container.style.cssText += cssVars;\n        }\n\n        // Update preview to reflect new theme\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     * @param {string} themeName - Resolved theme name\n     */\n    _applyResolvedTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      \n      // Update container with resolved theme, but keep auto in data-theme for tracking\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      // Apply CSS variables\n      if (themeObj && themeObj.colors) {\n        const cssVars = themeToCSSVars(themeObj.colors);\n        this.container.style.cssText += cssVars;\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAutoThemeListener() {\n      if (!window.matchMedia) return;\n\n      this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n      this.autoThemeListener = (event) => {\n        const resolvedTheme = event.matches ? 'cave' : 'solar';\n        this._applyResolvedTheme(resolvedTheme);\n      };\n\n      // Use addEventListener if available (modern browsers)\n      if (this.autoThemeMediaQuery.addEventListener) {\n        this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener);\n      } else if (this.autoThemeMediaQuery.addListener) {\n        // Fallback for older browsers\n        this.autoThemeMediaQuery.addListener(this.autoThemeListener);\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAutoThemeListener() {\n      if (this.autoThemeMediaQuery && this.autoThemeListener) {\n        if (this.autoThemeMediaQuery.removeEventListener) {\n          this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener);\n        } else if (this.autoThemeMediaQuery.removeListener) {\n          // Fallback for older browsers\n          this.autoThemeMediaQuery.removeListener(this.autoThemeListener);\n        }\n        this.autoThemeMediaQuery = null;\n        this.autoThemeListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAutoThemeListener();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAutoThemeListener();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAutoThemeListener();\n // Apply the initial resolved theme\n const resolvedTheme = resolveAutoTheme('auto');\n OverType._applyGlobalResolvedTheme(resolvedTheme, customColors);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances - update container theme attribute\n document.querySelectorAll('.overtype-container').forEach(container => {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n container.setAttribute('data-theme', themeName);\n }\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n // Set the theme attribute to update the theme name\n if (themeName && typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', themeName);\n }\n // Also call refreshTheme() to handle cases where the theme name stays the same\n // but the theme object's properties have changed\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n */\n static _applyGlobalResolvedTheme(themeName, customColors = null) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all containers with resolved theme, but keep 'auto' for tracking\n document.querySelectorAll('.overtype-container').forEach(container => {\n container.setAttribute('data-theme', 'auto');\n container.setAttribute('data-resolved-theme', themeName);\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', 'auto');\n webComponent.setAttribute('data-resolved-theme', themeName);\n }\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAutoThemeListener() {\n if (!window.matchMedia) return;\n\n OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n OverType.autoThemeListener = (event) => {\n const resolvedTheme = event.matches ? 'cave' : 'solar';\n OverType._applyGlobalResolvedTheme(resolvedTheme);\n };\n\n // Use addEventListener if available (modern browsers)\n if (OverType.autoThemeMediaQuery.addEventListener) {\n OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener);\n } else if (OverType.autoThemeMediaQuery.addListener) {\n // Fallback for older browsers\n OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener);\n }\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAutoThemeListener() {\n if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) {\n if (OverType.autoThemeMediaQuery.removeEventListener) {\n OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener);\n } else if (OverType.autoThemeMediaQuery.removeListener) {\n // Fallback for older browsers\n OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener);\n }\n OverType.autoThemeMediaQuery = null;\n OverType.autoThemeListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], - "mappings": "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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;;;;;;;;;;;;;AC92BO,IAAM,UAA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", - "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons", "themeName"] + "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Clean up existing auto theme listener if any\n      this._cleanupAuto();\n\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Handle auto theme\n      if (theme === 'auto') {\n        this._setupAuto();\n        // Apply the initial resolved theme\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        // Get theme object for non-auto themes\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n        // Update container theme attribute\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        // Apply CSS variables to container for instance override\n        if (themeObj && themeObj.colors) {\n          const cssVars = themeToCSSVars(themeObj.colors);\n          this.container.style.cssText += cssVars;\n        }\n\n        // Update preview to reflect new theme\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     * @param {string} themeName - Resolved theme name\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      \n      // Update container with resolved theme, but keep auto in data-theme for tracking\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      // Apply CSS variables\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      // Add this instance to the global auto instances set\n      OverType._autoInstances.add(this);\n\n      // Setup global listener if not already setup\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          // Notify all auto-themed instances\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        if (OverType._mq.addEventListener) {\n          OverType._mq.addEventListener('change', OverType._mqListener);\n        } else if (OverType._mq.addListener) {\n          OverType._mq.addListener(OverType._mqListener);\n        }\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      // Remove this instance from the auto instances set\n      OverType._autoInstances.delete(this);\n\n      // If no more auto instances, cleanup the global listener\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        if (OverType._mq.removeEventListener) {\n          OverType._mq.removeEventListener('change', OverType._mqListener);\n        } else if (OverType._mq.removeListener) {\n          OverType._mq.removeListener(OverType._mqListener);\n        }\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n // Single query for containers and wrappers\n const containers = document.querySelectorAll('.overtype-container');\n const wrappers = document.querySelectorAll('.overtype-wrapper');\n \n containers.forEach(el => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n });\n \n wrappers.forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n if (isAuto) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n } else {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n wrapper._instance?.updatePreview();\n });\n \n // Update web components\n document.querySelectorAll('overtype-editor').forEach(wc => {\n if (isAuto) {\n wc.setAttribute?.('theme', 'auto');\n wc.setAttribute?.('data-resolved-theme', themeName);\n } else {\n wc.setAttribute?.('theme', themeName);\n }\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n if (OverType._globalAutoMq.addEventListener) {\n OverType._globalAutoMq.addEventListener('change', OverType._globalAutoListener);\n } else if (OverType._globalAutoMq.addListener) {\n OverType._globalAutoMq.addListener(OverType._globalAutoListener);\n }\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n if (OverType._globalAutoMq.removeEventListener) {\n OverType._globalAutoMq.removeEventListener('change', OverType._globalAutoListener);\n } else if (OverType._globalAutoMq.removeListener) {\n OverType._globalAutoMq.removeListener(OverType._globalAutoListener);\n }\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], + "mappings": "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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;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", + "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons"] } diff --git a/dist/overtype.js b/dist/overtype.js index d6124b0..9795e3b 100644 --- a/dist/overtype.js +++ b/dist/overtype.js @@ -961,12 +961,14 @@ var OverType = (() => { } return theme; } + var _mq = null; function resolveAutoTheme(themeName) { - if (themeName !== "auto") { + if (themeName !== "auto") return themeName; + if (!_mq && window.matchMedia) { + _mq = window.matchMedia("(prefers-color-scheme: dark)"); } - const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; - return isDarkMode ? "cave" : "solar"; + return (_mq == null ? void 0 : _mq.matches) ? "cave" : "solar"; } function themeToCSSVars(colors) { const vars = []; @@ -3399,7 +3401,7 @@ ${blockSuffix}` : suffix; return false; } var _OverType = class _OverType { - // Listener function for auto theme changes + // Global auto theme listener /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4099,12 +4101,11 @@ ${blockSuffix}` : suffix; * @returns {this} Returns this for chaining */ setTheme(theme) { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.instanceTheme = theme; if (theme === "auto") { - this._setupAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - this._applyResolvedTheme(resolvedTheme); + this._setupAuto(); + this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; @@ -4124,13 +4125,12 @@ ${blockSuffix}` : suffix; * @private * @param {string} themeName - Resolved theme name */ - _applyResolvedTheme(themeName) { + _applyTheme(themeName) { const themeObj = getTheme(themeName); this.container.setAttribute("data-theme", "auto"); this.container.setAttribute("data-resolved-theme", themeName); - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4138,33 +4138,37 @@ ${blockSuffix}` : suffix; * Setup auto theme listener for instance * @private */ - _setupAutoThemeListener() { + _setupAuto() { if (!window.matchMedia) return; - this.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - this.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - this._applyResolvedTheme(resolvedTheme); - }; - if (this.autoThemeMediaQuery.addEventListener) { - this.autoThemeMediaQuery.addEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.addListener) { - this.autoThemeMediaQuery.addListener(this.autoThemeListener); + _OverType._autoInstances.add(this); + if (!_OverType._mq) { + _OverType._mq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._mqListener = (e) => { + const theme = e.matches ? "cave" : "solar"; + _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); + }; + if (_OverType._mq.addEventListener) { + _OverType._mq.addEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.addListener) { + _OverType._mq.addListener(_OverType._mqListener); + } } } /** * Clean up auto theme listener for instance * @private */ - _cleanupAutoThemeListener() { - if (this.autoThemeMediaQuery && this.autoThemeListener) { - if (this.autoThemeMediaQuery.removeEventListener) { - this.autoThemeMediaQuery.removeEventListener("change", this.autoThemeListener); - } else if (this.autoThemeMediaQuery.removeListener) { - this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + _cleanupAuto() { + _OverType._autoInstances.delete(this); + if (_OverType._autoInstances.size === 0 && _OverType._mq) { + if (_OverType._mq.removeEventListener) { + _OverType._mq.removeEventListener("change", _OverType._mqListener); + } else if (_OverType._mq.removeListener) { + _OverType._mq.removeListener(_OverType._mqListener); } - this.autoThemeMediaQuery = null; - this.autoThemeListener = null; + _OverType._mq = null; + _OverType._mqListener = null; } } /** @@ -4319,7 +4323,7 @@ ${blockSuffix}` : suffix; * Destroy the editor instance */ destroy() { - this._cleanupAutoThemeListener(); + this._cleanupAuto(); this.element.overTypeInstance = null; _OverType.instances.delete(this.element); if (this.shortcuts) { @@ -4419,17 +4423,54 @@ ${blockSuffix}` : suffix; document.head.appendChild(styleEl); _OverType.stylesInjected = true; } + /** + * Helper to update DOM elements with theme attributes + * @private + */ + static _updateThemeAttrs(themeName, isAuto = false) { + const containers = document.querySelectorAll(".overtype-container"); + const wrappers = document.querySelectorAll(".overtype-wrapper"); + containers.forEach((el) => { + if (isAuto) { + el.setAttribute("data-theme", "auto"); + el.setAttribute("data-resolved-theme", themeName); + } else { + el.setAttribute("data-theme", themeName); + } + }); + wrappers.forEach((wrapper) => { + var _a; + if (!wrapper.closest(".overtype-container")) { + if (isAuto) { + wrapper.setAttribute("data-theme", "auto"); + wrapper.setAttribute("data-resolved-theme", themeName); + } else { + wrapper.setAttribute("data-theme", themeName); + } + } + (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + }); + document.querySelectorAll("overtype-editor").forEach((wc) => { + var _a, _b, _c, _d; + if (isAuto) { + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); + } else { + (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); + } + (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + }); + } /** * Set global theme for all OverType instances * @param {string|Object} theme - Theme name or custom theme object * @param {Object} customColors - Optional color overrides */ static setTheme(theme, customColors = null) { - _OverType._cleanupGlobalAutoThemeListener(); + _OverType._cleanupGlobalAuto(); if (theme === "auto") { - _OverType._setupGlobalAutoThemeListener(); - const resolvedTheme = resolveAutoTheme("auto"); - _OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + _OverType._setupGlobalAuto(); + _OverType._applyGlobalTheme(resolveAutoTheme("auto"), customColors, true); } else { let themeObj = typeof theme === "string" ? getTheme(theme) : theme; if (customColors) { @@ -4437,33 +4478,10 @@ ${blockSuffix}` : suffix; } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - container.setAttribute("data-theme", themeName2); - } - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - const themeName2 = typeof themeObj === "string" ? themeObj : themeObj.name; - if (themeName2) { - wrapper.setAttribute("data-theme", themeName2); - } - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (themeName && typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + const themeName = themeObj.name || theme; + if (themeName) { + _OverType._updateThemeAttrs(themeName); + } } } /** @@ -4471,69 +4489,47 @@ ${blockSuffix}` : suffix; * @private * @param {string} themeName - Resolved theme name * @param {Object} customColors - Optional color overrides + * @param {boolean} isAuto - Whether this is an auto theme */ - static _applyGlobalResolvedTheme(themeName, customColors = null) { + static _applyGlobalTheme(themeName, customColors = null, isAuto = false) { let themeObj = getTheme(themeName); if (customColors) { themeObj = mergeTheme(themeObj, customColors); } _OverType.currentTheme = themeObj; _OverType.injectStyles(true); - document.querySelectorAll(".overtype-container").forEach((container) => { - container.setAttribute("data-theme", "auto"); - container.setAttribute("data-resolved-theme", themeName); - }); - document.querySelectorAll(".overtype-wrapper").forEach((wrapper) => { - if (!wrapper.closest(".overtype-container")) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - document.querySelectorAll("overtype-editor").forEach((webComponent) => { - if (typeof webComponent.setAttribute === "function") { - webComponent.setAttribute("theme", "auto"); - webComponent.setAttribute("data-resolved-theme", themeName); - } - if (typeof webComponent.refreshTheme === "function") { - webComponent.refreshTheme(); - } - }); + _OverType._updateThemeAttrs(themeName, isAuto); } /** * Setup global auto theme listener * @private */ - static _setupGlobalAutoThemeListener() { - if (!window.matchMedia) + static _setupGlobalAuto() { + if (!window.matchMedia || _OverType._globalAutoMq) return; - _OverType.autoThemeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); - _OverType.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? "cave" : "solar"; - _OverType._applyGlobalResolvedTheme(resolvedTheme); + _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); + _OverType._globalAutoListener = (e) => { + _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType.autoThemeMediaQuery.addEventListener) { - _OverType.autoThemeMediaQuery.addEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.addListener) { - _OverType.autoThemeMediaQuery.addListener(_OverType.autoThemeListener); + if (_OverType._globalAutoMq.addEventListener) { + _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.addListener) { + _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); } } /** * Clean up global auto theme listener * @private */ - static _cleanupGlobalAutoThemeListener() { - if (_OverType.autoThemeMediaQuery && _OverType.autoThemeListener) { - if (_OverType.autoThemeMediaQuery.removeEventListener) { - _OverType.autoThemeMediaQuery.removeEventListener("change", _OverType.autoThemeListener); - } else if (_OverType.autoThemeMediaQuery.removeListener) { - _OverType.autoThemeMediaQuery.removeListener(_OverType.autoThemeListener); + static _cleanupGlobalAuto() { + if (_OverType._globalAutoMq && _OverType._globalAutoListener) { + if (_OverType._globalAutoMq.removeEventListener) { + _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); + } else if (_OverType._globalAutoMq.removeListener) { + _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); } - _OverType.autoThemeMediaQuery = null; - _OverType.autoThemeListener = null; + _OverType._globalAutoMq = null; + _OverType._globalAutoListener = null; } } /** @@ -4637,9 +4633,15 @@ ${blockSuffix}` : suffix; __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); - __publicField(_OverType, "autoThemeMediaQuery", null); - // Media query for auto theme switching - __publicField(_OverType, "autoThemeListener", null); + __publicField(_OverType, "_mq", null); + // Shared media query for auto theme + __publicField(_OverType, "_mqListener", null); + // Shared listener + __publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); + // Track auto-themed instances + __publicField(_OverType, "_globalAutoMq", null); + // Global auto theme media query + __publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; OverType.ShortcutsManager = ShortcutsManager; diff --git a/dist/overtype.js.map b/dist/overtype.js.map index dda5d5d..7f18047 100644 --- a/dist/overtype.js.map +++ b/dist/overtype.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/overtype.js", "../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js"], - "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static autoThemeMediaQuery = null; // Media query for auto theme switching\n static autoThemeListener = null; // Listener function for auto theme changes\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Clean up existing auto theme listener if any\n      this._cleanupAutoThemeListener();\n\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Handle auto theme\n      if (theme === 'auto') {\n        this._setupAutoThemeListener();\n        // Apply the initial resolved theme\n        const resolvedTheme = resolveAutoTheme('auto');\n        this._applyResolvedTheme(resolvedTheme);\n      } else {\n        // Get theme object for non-auto themes\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n        // Update container theme attribute\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        // Apply CSS variables to container for instance override\n        if (themeObj && themeObj.colors) {\n          const cssVars = themeToCSSVars(themeObj.colors);\n          this.container.style.cssText += cssVars;\n        }\n\n        // Update preview to reflect new theme\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     * @param {string} themeName - Resolved theme name\n     */\n    _applyResolvedTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      \n      // Update container with resolved theme, but keep auto in data-theme for tracking\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      // Apply CSS variables\n      if (themeObj && themeObj.colors) {\n        const cssVars = themeToCSSVars(themeObj.colors);\n        this.container.style.cssText += cssVars;\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAutoThemeListener() {\n      if (!window.matchMedia) return;\n\n      this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n      this.autoThemeListener = (event) => {\n        const resolvedTheme = event.matches ? 'cave' : 'solar';\n        this._applyResolvedTheme(resolvedTheme);\n      };\n\n      // Use addEventListener if available (modern browsers)\n      if (this.autoThemeMediaQuery.addEventListener) {\n        this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener);\n      } else if (this.autoThemeMediaQuery.addListener) {\n        // Fallback for older browsers\n        this.autoThemeMediaQuery.addListener(this.autoThemeListener);\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAutoThemeListener() {\n      if (this.autoThemeMediaQuery && this.autoThemeListener) {\n        if (this.autoThemeMediaQuery.removeEventListener) {\n          this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener);\n        } else if (this.autoThemeMediaQuery.removeListener) {\n          // Fallback for older browsers\n          this.autoThemeMediaQuery.removeListener(this.autoThemeListener);\n        }\n        this.autoThemeMediaQuery = null;\n        this.autoThemeListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAutoThemeListener();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAutoThemeListener();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAutoThemeListener();\n // Apply the initial resolved theme\n const resolvedTheme = resolveAutoTheme('auto');\n OverType._applyGlobalResolvedTheme(resolvedTheme, customColors);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances - update container theme attribute\n document.querySelectorAll('.overtype-container').forEach(container => {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n container.setAttribute('data-theme', themeName);\n }\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n if (themeName) {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n // Set the theme attribute to update the theme name\n if (themeName && typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', themeName);\n }\n // Also call refreshTheme() to handle cases where the theme name stays the same\n // but the theme object's properties have changed\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n */\n static _applyGlobalResolvedTheme(themeName, customColors = null) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all containers with resolved theme, but keep 'auto' for tracking\n document.querySelectorAll('.overtype-container').forEach(container => {\n container.setAttribute('data-theme', 'auto');\n container.setAttribute('data-resolved-theme', themeName);\n });\n\n // Also handle any old-style wrappers without containers\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n }\n\n // Trigger preview update for the instance\n const instance = wrapper._instance;\n if (instance) {\n instance.updatePreview();\n }\n });\n\n // Update web components\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.setAttribute === 'function') {\n webComponent.setAttribute('theme', 'auto');\n webComponent.setAttribute('data-resolved-theme', themeName);\n }\n if (typeof webComponent.refreshTheme === 'function') {\n webComponent.refreshTheme();\n }\n });\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAutoThemeListener() {\n if (!window.matchMedia) return;\n\n OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n OverType.autoThemeListener = (event) => {\n const resolvedTheme = event.matches ? 'cave' : 'solar';\n OverType._applyGlobalResolvedTheme(resolvedTheme);\n };\n\n // Use addEventListener if available (modern browsers)\n if (OverType.autoThemeMediaQuery.addEventListener) {\n OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener);\n } else if (OverType.autoThemeMediaQuery.addListener) {\n // Fallback for older browsers\n OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener);\n }\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAutoThemeListener() {\n if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) {\n if (OverType.autoThemeMediaQuery.removeEventListener) {\n OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener);\n } else if (OverType.autoThemeMediaQuery.removeListener) {\n // Fallback for older browsers\n OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener);\n }\n OverType.autoThemeMediaQuery = null;\n OverType.autoThemeListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') {\n return themeName;\n }\n\n // Check for system dark mode preference\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], - "mappings": "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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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", - "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons", "themeName"] + "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Clean up existing auto theme listener if any\n      this._cleanupAuto();\n\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Handle auto theme\n      if (theme === 'auto') {\n        this._setupAuto();\n        // Apply the initial resolved theme\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        // Get theme object for non-auto themes\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n        // Update container theme attribute\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        // Apply CSS variables to container for instance override\n        if (themeObj && themeObj.colors) {\n          const cssVars = themeToCSSVars(themeObj.colors);\n          this.container.style.cssText += cssVars;\n        }\n\n        // Update preview to reflect new theme\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     * @param {string} themeName - Resolved theme name\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      \n      // Update container with resolved theme, but keep auto in data-theme for tracking\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      // Apply CSS variables\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      // Add this instance to the global auto instances set\n      OverType._autoInstances.add(this);\n\n      // Setup global listener if not already setup\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          // Notify all auto-themed instances\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        if (OverType._mq.addEventListener) {\n          OverType._mq.addEventListener('change', OverType._mqListener);\n        } else if (OverType._mq.addListener) {\n          OverType._mq.addListener(OverType._mqListener);\n        }\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      // Remove this instance from the auto instances set\n      OverType._autoInstances.delete(this);\n\n      // If no more auto instances, cleanup the global listener\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        if (OverType._mq.removeEventListener) {\n          OverType._mq.removeEventListener('change', OverType._mqListener);\n        } else if (OverType._mq.removeListener) {\n          OverType._mq.removeListener(OverType._mqListener);\n        }\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n // Single query for containers and wrappers\n const containers = document.querySelectorAll('.overtype-container');\n const wrappers = document.querySelectorAll('.overtype-wrapper');\n \n containers.forEach(el => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n });\n \n wrappers.forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n if (isAuto) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n } else {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n wrapper._instance?.updatePreview();\n });\n \n // Update web components\n document.querySelectorAll('overtype-editor').forEach(wc => {\n if (isAuto) {\n wc.setAttribute?.('theme', 'auto');\n wc.setAttribute?.('data-resolved-theme', themeName);\n } else {\n wc.setAttribute?.('theme', themeName);\n }\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n if (OverType._globalAutoMq.addEventListener) {\n OverType._globalAutoMq.addEventListener('change', OverType._globalAutoListener);\n } else if (OverType._globalAutoMq.addListener) {\n OverType._globalAutoMq.addListener(OverType._globalAutoListener);\n }\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n if (OverType._globalAutoMq.removeEventListener) {\n OverType._globalAutoMq.removeEventListener('change', OverType._globalAutoListener);\n } else if (OverType._globalAutoMq.removeListener) {\n OverType._globalAutoMq.removeListener(OverType._globalAutoListener);\n }\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], + "mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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", + "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons"] } diff --git a/dist/overtype.min.js b/dist/overtype.min.js index 8507bd9..01cc017 100644 --- a/dist/overtype.min.js +++ b/dist/overtype.min.js @@ -5,15 +5,15 @@ * @author David Miranda * https://github.com/panphora/overtype */ -var OverType=(()=>{var z=Object.defineProperty;var je=Object.getOwnPropertyDescriptor;var ze=Object.getOwnPropertyNames;var Fe=Object.prototype.hasOwnProperty;var Re=(o,e,t)=>e in o?z(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Ve=(o,e)=>{for(var t in e)z(o,t,{get:e[t],enumerable:!0})},Ue=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ze(e))!Fe.call(o,i)&&i!==t&&z(o,i,{get:()=>e[i],enumerable:!(n=je(e,i))||n.enumerable});return o};var De=o=>Ue(z({},"__esModule",{value:!0}),o);var T=(o,e,t)=>(Re(o,typeof e!="symbol"?e+"":e,t),t);var st={};Ve(st,{OverType:()=>I,default:()=>rt,defaultToolbarButtons:()=>_,toolbarButtons:()=>k});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,n=>t[n])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,n,i)=>{let r=n.length;return`${n} ${i}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,n)=>`> ${n}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(n,i,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${i}
  • ${s}
  • `}else return`${i}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),n=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>n.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,n,i)=>{let r=`--link-${this.linkIndex++}`;return`
    [${n}](${i})`})}static identifyAndProtectSanctuaries(e){let t=new Map,n=0,i=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,u=h+a[2].length;r.push({start:h,end:u})}let p=new RegExp("(?c>=v.start&&h<=v.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((c,h)=>h.index-c.index),l.forEach(c=>{let h=`\uE000${n++}\uE001`;t.set(h,{type:"code",original:c.match,openTicks:c.openTicks,content:c.content,closeTicks:c.closeTicks}),i=i.substring(0,c.index)+h+i.substring(c.index+c.match.length)}),i=i.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(c,h,u)=>{let v=`\uE000${n++}\uE001`;return t.set(v,{type:"link",original:c,linkText:h,url:u}),v}),{protectedText:i,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((i,r)=>{let s=e.indexOf(i),a=e.indexOf(r);return s-a}).forEach(i=>{let r=t.get(i),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,c)=>{if(a.includes(c)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(c,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let p=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(i,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:n}=this.identifyAndProtectSanctuaries(e),i=t;return i=this.parseStrikethrough(i),i=this.parseBold(i),i=this.parseItalic(i),i=this.restoreAndTransformSanctuaries(i,n),i}static parseLine(e,t=!1){let n=this.escapeHtml(e);n=this.preserveIndentation(n,e);let i=this.parseHorizontalRule(n);if(i)return i;let r=this.parseCodeBlock(n);return r||(n=this.parseHeader(n),n=this.parseBlockquote(n),n=this.parseTaskList(n,t),n=this.parseBulletList(n),n=this.parseNumberedList(n),n=this.parseInlineElements(n),n.trim()===""?"
     
    ":`
    ${n}
    `)}static parse(e,t=-1,n=!1,i,r=!1){this.resetLinkIndex();let s=e.split(` -`),a=!1,d=s.map((l,c)=>{if(n&&c===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let u=this.escapeHtml(l);return`
    ${this.preserveIndentation(u,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,i)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let n=document.createElement("div");n.innerHTML=e;let i=null,r=null,s=null,a=!1,p=Array.from(n.children);for(let d=0;d0&&(s._codeContent+=` -`);let v=l.textContent.replace(/\u00A0/g," ");s._codeContent+=v,u.textContent.length>0&&(u.textContent+=` -`),u.textContent+=v,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let u=h.classList.contains("bullet-list"),v=h.classList.contains("ordered-list");if(!u&&!v){i=null,r=null;continue}let f=u?"ul":"ol";(!i||r!==f)&&(i=document.createElement(f),n.insertBefore(i,l),r=f);let g=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))g.push(y.cloneNode(!0));else if(y===h)break;g.forEach(y=>{h.insertBefore(y,h.firstChild)}),i.appendChild(h),l.remove()}else i=null,r=null}return n.innerHTML}static postProcessHTMLManual(e,t){let n=e;n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(p=>{let d=p.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let c=d[1];return l[0].replace(/
    • /,`
    • ${c}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(p=>{let d=p.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let c=d[1];return l[0].replace(/
    2. /,`
    3. ${c}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let i=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return n=n.replace(i,(r,s,a,p)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(g=>g.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` -`),c=s.slice(3).trim(),h=c?` class="language-${c}"`:"",u=l,v=t||this.codeHighlighter;if(v)try{let g=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=v(g,c);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(u=y)}catch(g){console.warn("Code highlighting failed:",g)}let f=`
    ${s}
    `;return f+=`
    ${u}
    `,f+=`
    ${p}
    `,f}),n}static getListContext(e,t){let n=e.split(` -`),i=0,r=0,s=0;for(let h=0;h=t){r=h,s=i;break}i+=u+1}let a=n[r],p=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:p,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:p,markerEndPos:s+l[1].length+l[2].length+1};let c=a.match(this.LIST_PATTERNS.numbered);return c?{inList:!0,listType:"numbered",indent:c[1],marker:parseInt(c[2]),content:c[3],lineStart:s,lineEnd:p,markerEndPos:s+c[1].length+c[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:p,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` -`),n=new Map,i=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let p=a[1],d=p.length,l=a[3];i||n.clear();let c=(n.get(d)||0)+1;n.set(d,c);for(let[h]of n)h>d&&n.delete(h);return i=!0,`${p}${c}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(i=!1,n.clear()),s}).join(` -`)}};T(S,"linkIndex",0),T(S,"codeHighlighter",null),T(S,"customSyntax",null),T(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var O=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.performAction(i,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},Y={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},qe={name:"auto",colors:A.colors},ee={solar:A,cave:Y,auto:qe,light:A,dark:Y};function M(o){return typeof o=="string"?{...ee[o]||ee.solar,name:o}:o}function W(o){return o!=="auto"?o:window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"cave":"solar"}function N(o){let e=[];for(let[t,n]of Object.entries(o)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${n};`)}return e.join(` -`)}function Q(o,e={}){return{...o,colors:{...o.colors,...e}}}function te(o={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:n='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:s={}}=o,a=Object.keys(s).length>0?` +var OverType=(()=>{var F=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var Fe=Object.getOwnPropertyNames;var qe=Object.prototype.hasOwnProperty;var Re=(o,e,t)=>e in o?F(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Ve=(o,e)=>{for(var t in e)F(o,t,{get:e[t],enumerable:!0})},Ue=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Fe(e))!qe.call(o,i)&&i!==t&&F(o,i,{get:()=>e[i],enumerable:!(n=Oe(e,i))||n.enumerable});return o};var De=o=>Ue(F({},"__esModule",{value:!0}),o);var E=(o,e,t)=>(Re(o,typeof e!="symbol"?e+"":e,t),t);var at={};Ve(at,{OverType:()=>I,default:()=>st,defaultToolbarButtons:()=>N,toolbarButtons:()=>k});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,n=>t[n])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,n,i)=>{let r=n.length;return`${n} ${i}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,n)=>`> ${n}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(n,i,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${i}
  • ${s}
  • `}else return`${i}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),n=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>n.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,n,i)=>{let r=`--link-${this.linkIndex++}`;return`[${n}](${i})`})}static identifyAndProtectSanctuaries(e){let t=new Map,n=0,i=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,m=h+a[2].length;r.push({start:h,end:m})}let c=new RegExp("(?p>=g.start&&h<=g.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((p,h)=>h.index-p.index),l.forEach(p=>{let h=`\uE000${n++}\uE001`;t.set(h,{type:"code",original:p.match,openTicks:p.openTicks,content:p.content,closeTicks:p.closeTicks}),i=i.substring(0,p.index)+h+i.substring(p.index+p.match.length)}),i=i.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(p,h,m)=>{let g=`\uE000${n++}\uE001`;return t.set(g,{type:"link",original:p,linkText:h,url:m}),g}),{protectedText:i,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((i,r)=>{let s=e.indexOf(i),a=e.indexOf(r);return s-a}).forEach(i=>{let r=t.get(i),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,p)=>{if(a.includes(p)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(p,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let c=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(i,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:n}=this.identifyAndProtectSanctuaries(e),i=t;return i=this.parseStrikethrough(i),i=this.parseBold(i),i=this.parseItalic(i),i=this.restoreAndTransformSanctuaries(i,n),i}static parseLine(e,t=!1){let n=this.escapeHtml(e);n=this.preserveIndentation(n,e);let i=this.parseHorizontalRule(n);if(i)return i;let r=this.parseCodeBlock(n);return r||(n=this.parseHeader(n),n=this.parseBlockquote(n),n=this.parseTaskList(n,t),n=this.parseBulletList(n),n=this.parseNumberedList(n),n=this.parseInlineElements(n),n.trim()===""?"
     
    ":`
    ${n}
    `)}static parse(e,t=-1,n=!1,i,r=!1){this.resetLinkIndex();let s=e.split(` +`),a=!1,d=s.map((l,p)=>{if(n&&p===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let m=this.escapeHtml(l);return`
    ${this.preserveIndentation(m,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,i)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let n=document.createElement("div");n.innerHTML=e;let i=null,r=null,s=null,a=!1,c=Array.from(n.children);for(let d=0;d0&&(s._codeContent+=` +`);let g=l.textContent.replace(/\u00A0/g," ");s._codeContent+=g,m.textContent.length>0&&(m.textContent+=` +`),m.textContent+=g,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let m=h.classList.contains("bullet-list"),g=h.classList.contains("ordered-list");if(!m&&!g){i=null,r=null;continue}let f=m?"ul":"ol";(!i||r!==f)&&(i=document.createElement(f),n.insertBefore(i,l),r=f);let v=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))v.push(y.cloneNode(!0));else if(y===h)break;v.forEach(y=>{h.insertBefore(y,h.firstChild)}),i.appendChild(h),l.remove()}else i=null,r=null}return n.innerHTML}static postProcessHTMLManual(e,t){let n=e;n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    • /,`
    • ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    2. /,`
    3. ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let i=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return n=n.replace(i,(r,s,a,c)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(v=>v.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` +`),p=s.slice(3).trim(),h=p?` class="language-${p}"`:"",m=l,g=t||this.codeHighlighter;if(g)try{let v=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=g(v,p);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(m=y)}catch(v){console.warn("Code highlighting failed:",v)}let f=`
    ${s}
    `;return f+=`
    ${m}
    `,f+=`
    ${c}
    `,f}),n}static getListContext(e,t){let n=e.split(` +`),i=0,r=0,s=0;for(let h=0;h=t){r=h,s=i;break}i+=m+1}let a=n[r],c=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:c,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:c,markerEndPos:s+l[1].length+l[2].length+1};let p=a.match(this.LIST_PATTERNS.numbered);return p?{inList:!0,listType:"numbered",indent:p[1],marker:parseInt(p[2]),content:p[3],lineStart:s,lineEnd:c,markerEndPos:s+p[1].length+p[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:c,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` +`),n=new Map,i=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let c=a[1],d=c.length,l=a[3];i||n.clear();let p=(n.get(d)||0)+1;n.set(d,p);for(let[h]of n)h>d&&n.delete(h);return i=!0,`${c}${p}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(i=!1,n.clear()),s}).join(` +`)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var j=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.performAction(i,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ee={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},We={name:"auto",colors:A.colors},te={solar:A,cave:ee,auto:We,light:A,dark:ee};function M(o){return typeof o=="string"?{...te[o]||te.solar,name:o}:o}var z=null;function K(o){return o!=="auto"?o:(!z&&window.matchMedia&&(z=window.matchMedia("(prefers-color-scheme: dark)")),z!=null&&z.matches?"cave":"solar")}function _(o){let e=[];for(let[t,n]of Object.entries(o)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${n};`)}return e.join(` +`)}function G(o,e={}){return{...o,colors:{...o.colors,...e}}}function ne(o={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:n='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:s={}}=o,a=Object.keys(s).length>0?` @media (max-width: 640px) { .overtype-wrapper .overtype-input, .overtype-wrapper .overtype-preview { @@ -21,7 +21,7 @@ var OverType=(()=>{var z=Object.defineProperty;var je=Object.getOwnPropertyDescr `)} } } - `:"",p=r&&r.colors?N(r.colors):"";return` + `:"",c=r&&r.colors?_(r.colors):"";return` /* OverType Editor Styles */ /* Middle-ground CSS Reset - Prevent parent styles from leaking in */ @@ -62,9 +62,9 @@ var OverType=(()=>{var z=Object.defineProperty;var je=Object.getOwnPropertyDescr overflow: visible !important; /* Allow dropdown to overflow container */ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important; text-align: left !important; - ${p?` + ${c?` /* Theme Variables */ - ${p}`:""} + ${c}`:""} } /* Force left alignment for all elements in the editor */ @@ -861,28 +861,28 @@ var OverType=(()=>{var z=Object.defineProperty;var je=Object.getOwnPropertyDescr } ${a} - `}var We=Object.defineProperty,ne=Object.getOwnPropertySymbols,Qe=Object.prototype.hasOwnProperty,Ke=Object.prototype.propertyIsEnumerable,oe=(o,e,t)=>e in o?We(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,ie=(o,e)=>{for(var t in e||(e={}))Qe.call(e,t)&&oe(o,t,e[t]);if(ne)for(var t of ne(e))Ke.call(e,t)&&oe(o,t,e[t]);return o},E={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Ge(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return ie(ie({},Ge()),o)}var R=!1;function Ze(){return R}function b(o,e,t){R&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function F(o,e){if(!R)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function le(o){R&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function B(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Ze();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),p=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(p.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` -`).length,"lines")}catch(c){H=!1,i&&console.log("execCommand threw error:",c)}o.contentEditable="false"}if(i&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let c=a+e+p,h=o.value;i&&(console.log("Expected length:",c.length),console.log("Actual length:",h.length)),h!==c&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(c.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!H)if(i&&console.log("Using manual insertion"),o.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(c){}o.value=a+e+p;try{document.execCommand("ms-endUndoUnit")}catch(c){}o.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,n),t!=null&&n!=null?o.setSelectionRange(t,n):o.setSelectionRange(r,o.selectionEnd),i&&(console.log("Final value length:",o.value.length),console.groupEnd())}function re(o){return o.trim().split(` -`).length>1}function Je(o,e){let t=e;for(;o[t]&&o[t-1]!=null&&!o[t-1].match(/\s/);)t--;return t}function Xe(o,e,t){let n=e,i=t?/\n/:/\s/;for(;o[n]&&!o[n].match(i);)n++;return n}function ce(o){let e=o.value.split(` -`),t=0;for(let n=0;n=t&&o.selectionStart=t&&o.selectionEnd0&&s[a-1]!==` + `}var Ke=Object.defineProperty,oe=Object.getOwnPropertySymbols,Ge=Object.prototype.hasOwnProperty,Ze=Object.prototype.propertyIsEnumerable,ie=(o,e,t)=>e in o?Ke(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,re=(o,e)=>{for(var t in e||(e={}))Ge.call(e,t)&&ie(o,t,e[t]);if(oe)for(var t of oe(e))Ze.call(e,t)&&ie(o,t,e[t]);return o},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Je(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return re(re({},Je()),o)}var R=!1;function Qe(){return R}function b(o,e,t){R&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function q(o,e){if(!R)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function ce(o){R&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function P(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Qe();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),c=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` +`).length,"lines")}catch(p){H=!1,i&&console.log("execCommand threw error:",p)}o.contentEditable="false"}if(i&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let p=a+e+c,h=o.value;i&&(console.log("Expected length:",p.length),console.log("Actual length:",h.length)),h!==p&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(p.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!H)if(i&&console.log("Using manual insertion"),o.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(p){}o.value=a+e+c;try{document.execCommand("ms-endUndoUnit")}catch(p){}o.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,n),t!=null&&n!=null?o.setSelectionRange(t,n):o.setSelectionRange(r,o.selectionEnd),i&&(console.log("Final value length:",o.value.length),console.groupEnd())}function se(o){return o.trim().split(` +`).length>1}function Xe(o,e){let t=e;for(;o[t]&&o[t-1]!=null&&!o[t-1].match(/\s/);)t--;return t}function Ye(o,e,t){let n=e,i=t?/\n/:/\s/;for(;o[n]&&!o[n].match(i);)n++;return n}function pe(o){let e=o.value.split(` +`),t=0;for(let n=0;n=t&&o.selectionStart=t&&o.selectionEnd0&&s[a-1]!==` `;)a--;if(r){let d=n;for(;d0?`${s} -`:i,y=re(f)&&a&&a.length>0?` -${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(g=` ${g}`)}f=Ye(o,g,y,e.multiline);let w=o.selectionStart,x=o.selectionEnd,P=p&&p.length>0&&y.indexOf(p)>-1&&f.length>0;if(c){let L=K(o);t=L.newlinesToAppend,n=L.newlinesToPrepend,g=t+i,y+=n}if(f.startsWith(g)&&f.endsWith(y)){let L=f.slice(g.length,f.length-y.length);if(u===v){let C=u-g.length;C=Math.max(C,w),C=Math.min(C,w+L.length),w=x=C}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if(P)if(l&&l.length>0&&f.match(l)){y=y.replace(p,f);let L=g+y;return w=x=w+g.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=g+f+y;return w=w+g.length+f.length+y.indexOf(p),x=w+p.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=g+f+y;w=u+g.length,x=v+g.length;let C=f.match(/^\s*|\s*$/g);if(h&&C){let J=C[0]||"",X=C[1]||"";L=J+g+f.trim()+y+X,w+=J.length,x-=X.length}return{text:L,selectionStart:w,selectionEnd:x}}}function pe(o,e){let{prefix:t,suffix:n,surroundWithNewlines:i}=e,r=o.value.slice(o.selectionStart,o.selectionEnd),s=o.selectionStart,a=o.selectionEnd,p=r.split(` -`);if(p.every(l=>l.startsWith(t)&&(!n||l.endsWith(n))))r=p.map(l=>{let c=l.slice(t.length);return n&&(c=c.slice(0,c.length-n.length)),c}).join(` -`),a=s+r.length;else if(r=p.map(l=>t+l+(n||"")).join(` -`),i){let{newlinesToAppend:l,newlinesToPrepend:c}=K(o);s+=l.length,a=s+r.length,r=l+r+c}return{text:r,selectionStart:s,selectionEnd:a}}function se(o){let e=o.split(` +`;)d++;o.selectionStart=a,o.selectionEnd=d}else pe(o);let c=e(o);if(t.adjustSelection){let l=o.value.slice(o.selectionStart,o.selectionEnd).startsWith(t.prefix),p=t.adjustSelection(l,n,i,a);c.selectionStart=p.start,c.selectionEnd=p.end}else if(t.prefix){let l=o.value.slice(o.selectionStart,o.selectionEnd).startsWith(t.prefix);r?l?(c.selectionStart=Math.max(n-t.prefix.length,a),c.selectionEnd=c.selectionStart):(c.selectionStart=n+t.prefix.length,c.selectionEnd=c.selectionStart):l?(c.selectionStart=Math.max(n-t.prefix.length,a),c.selectionEnd=Math.max(i-t.prefix.length,a)):(c.selectionStart=n+t.prefix.length,c.selectionEnd=i+t.prefix.length)}return c}function U(o,e){let t,n,{prefix:i,suffix:r,blockPrefix:s,blockSuffix:a,replaceNext:c,prefixSpace:d,scanFor:l,surroundWithNewlines:p,trimFirst:h}=e,m=o.selectionStart,g=o.selectionEnd,f=o.value.slice(o.selectionStart,o.selectionEnd),v=se(f)&&s&&s.length>0?`${s} +`:i,y=se(f)&&a&&a.length>0?` +${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(v=` ${v}`)}f=et(o,v,y,e.multiline);let w=o.selectionStart,x=o.selectionEnd,B=c&&c.length>0&&y.indexOf(c)>-1&&f.length>0;if(p){let L=Z(o);t=L.newlinesToAppend,n=L.newlinesToPrepend,v=t+i,y+=n}if(f.startsWith(v)&&f.endsWith(y)){let L=f.slice(v.length,f.length-y.length);if(m===g){let C=m-v.length;C=Math.max(C,w),C=Math.min(C,w+L.length),w=x=C}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if(B)if(l&&l.length>0&&f.match(l)){y=y.replace(c,f);let L=v+y;return w=x=w+v.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;return w=w+v.length+f.length+y.indexOf(c),x=w+c.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;w=m+v.length,x=g+v.length;let C=f.match(/^\s*|\s*$/g);if(h&&C){let X=C[0]||"",Y=C[1]||"";L=X+v+f.trim()+y+Y,w+=X.length,x-=Y.length}return{text:L,selectionStart:w,selectionEnd:x}}}function de(o,e){let{prefix:t,suffix:n,surroundWithNewlines:i}=e,r=o.value.slice(o.selectionStart,o.selectionEnd),s=o.selectionStart,a=o.selectionEnd,c=r.split(` +`);if(c.every(l=>l.startsWith(t)&&(!n||l.endsWith(n))))r=c.map(l=>{let p=l.slice(t.length);return n&&(p=p.slice(0,p.length-n.length)),p}).join(` +`),a=s+r.length;else if(r=c.map(l=>t+l+(n||"")).join(` +`),i){let{newlinesToAppend:l,newlinesToPrepend:p}=Z(o);s+=l.length,a=s+r.length,r=l+r+p}return{text:r,selectionStart:s,selectionEnd:a}}function ae(o){let e=o.split(` `),t=/^\d+\.\s+/,n=e.every(r=>t.test(r)),i=e;return n&&(i=e.map(r=>r.replace(t,""))),{text:i.join(` -`),processed:n}}function ae(o){let e=o.split(` +`),processed:n}}function le(o){let e=o.split(` `),t="- ",n=e.every(r=>r.startsWith(t)),i=e;return n&&(i=e.map(r=>r.slice(t.length))),{text:i.join(` -`),processed:n}}function j(o,e){return e?"- ":`${o+1}. `}function et(o,e){let t,n,i;return o.orderedList?(t=se(e),n=ae(t.text),i=n.text):(t=ae(e),n=se(t.text),i=n.text),[t,n,i]}function tt(o,e){let t=o.selectionStart===o.selectionEnd,n=o.selectionStart,i=o.selectionEnd;ce(o);let r=o.value.slice(o.selectionStart,o.selectionEnd),[s,a,p]=et(e,r),d=p.split(` -`).map((f,g)=>`${j(g,e.unorderedList)}${f}`),l=d.reduce((f,g,y)=>f+j(y,e.unorderedList).length,0),c=d.reduce((f,g,y)=>f+j(y,!e.unorderedList).length,0);if(s.processed)return t?(n=Math.max(n-j(0,e.unorderedList).length,0),i=n):(n=o.selectionStart,i=o.selectionEnd-l),{text:p,selectionStart:n,selectionEnd:i};let{newlinesToAppend:h,newlinesToPrepend:u}=K(o),v=h+d.join(` -`)+u;return t?(n=Math.max(n+j(0,e.unorderedList).length+h.length,0),i=n):a.processed?(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l-c):(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l),{text:v,selectionStart:n,selectionEnd:i}}function de(o,e){let t=V(o,n=>tt(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),p=/^\d+\.\s+/,d=/^- /,l=p.test(a),c=d.test(a),h=e.orderedList&&l||e.unorderedList&&c;if(i===r)if(h){let u=a.match(e.orderedList?p:d),v=u?u[0].length:0;return{start:Math.max(i-v,s),end:Math.max(i-v,s)}}else if(l||c){let u=a.match(l?p:d),v=u?u[0].length:0,g=(e.unorderedList?2:3)-v;return{start:i+g,end:i+g}}else{let u=e.unorderedList?2:3;return{start:i+u,end:i+u}}else if(h){let u=a.match(e.orderedList?p:d),v=u?u[0].length:0;return{start:Math.max(i-v,s),end:Math.max(r-v,s)}}else if(l||c){let u=a.match(l?p:d),v=u?u[0].length:0,g=(e.unorderedList?2:3)-v;return{start:i+g,end:r+g}}else{let u=e.unorderedList?2:3;return{start:i+u,end:r+u}}}});B(o,t)}function nt(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` -`),s=0,a="";for(let c of r){if(t>=s&&t<=s+c.length){a=c;break}s+=c.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let p=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(p,d);if(l.includes("**")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("**"),v=h.indexOf("**");u!==-1&&v!==-1&&e.push("bold")}if(l.includes("_")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("_"),v=h.indexOf("_");u!==-1&&v!==-1&&e.push("italic")}if(l.includes("`")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100));c.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let c=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),u=c.lastIndexOf("["),v=h.indexOf("]");u!==-1&&v!==-1&&i.slice(n+v+1,n+v+10).startsWith("(")&&e.push("link")}return e}function he(o){if(!o||o.disabled||o.readOnly)return;b("toggleBold","Starting"),F(o,"Before");let e=$(E.bold),t=U(o,e);le(t),B(o,t),F(o,"After")}function ue(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.italic),t=U(o,e);B(o,t)}function me(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.code),t=U(o,e);B(o,t)}function fe(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=$(E.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);B(o,r)}function ve(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.bulletList);de(o,e)}function ge(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.numberedList);de(o,e)}function ye(o){if(!o||o.disabled||o.readOnly)return;b("toggleQuote","Starting"),F(o,"Initial");let e=$(E.quote),t=V(o,n=>pe(n,e),{prefix:e.prefix});le(t),B(o,t),F(o,"Final")}function G(o){if(!o||o.disabled||o.readOnly)return;let e=$(E.taskList),t=V(o,n=>pe(n,e),{prefix:e.prefix});B(o,t)}function Z(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=$(E[n]||E.header1);b("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,p=s;for(;p>0&&r[p-1]!==` -`;)p--;let d=a;for(;d{let y=g.value.slice(g.selectionStart,g.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return v?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):h>0?(b("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=i.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=i.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:g.selectionStart,selectionEnd:g.selectionEnd}},{prefix:i.prefix,adjustSelection:(g,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${g}`),b("insertHeader",` - shouldToggleOff: ${v}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),v){let P=Math.max(y-u,x);return b("insertHeader",` - Removing header, adjusting by -${u}`),{start:P,end:y===w?P:Math.max(w-u,x)}}else if(u>0){let P=i.prefix.length-u;return b("insertHeader",` - Replacing header, adjusting by ${P}`),{start:y+P,end:w+P}}else return b("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:y+i.prefix.length,end:w+i.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),B(o,f)}function be(o){Z(o,1,!0)}function we(o){Z(o,2,!0)}function xe(o){Z(o,3,!0)}function ke(o){return nt(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=ke)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var q=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` +`),processed:n}}function O(o,e){return e?"- ":`${o+1}. `}function tt(o,e){let t,n,i;return o.orderedList?(t=ae(e),n=le(t.text),i=n.text):(t=le(e),n=ae(t.text),i=n.text),[t,n,i]}function nt(o,e){let t=o.selectionStart===o.selectionEnd,n=o.selectionStart,i=o.selectionEnd;pe(o);let r=o.value.slice(o.selectionStart,o.selectionEnd),[s,a,c]=tt(e,r),d=c.split(` +`).map((f,v)=>`${O(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+O(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+O(y,!e.unorderedList).length,0);if(s.processed)return t?(n=Math.max(n-O(0,e.unorderedList).length,0),i=n):(n=o.selectionStart,i=o.selectionEnd-l),{text:c,selectionStart:n,selectionEnd:i};let{newlinesToAppend:h,newlinesToPrepend:m}=Z(o),g=h+d.join(` +`)+m;return t?(n=Math.max(n+O(0,e.unorderedList).length+h.length,0),i=n):a.processed?(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l-p):(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l),{text:g,selectionStart:n,selectionEnd:i}}function ue(o,e){let t=V(o,n=>nt(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),h=e.orderedList&&l||e.unorderedList&&p;if(i===r)if(h){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(i-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:i+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:i+m}}else if(h){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(r-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:r+m}}}});P(o,t)}function ot(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` +`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(c,d);if(l.includes("**")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("**"),g=h.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("_"),g=h.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100));p.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("["),g=h.indexOf("]");m!==-1&&g!==-1&&i.slice(n+g+1,n+g+10).startsWith("(")&&e.push("link")}return e}function he(o){if(!o||o.disabled||o.readOnly)return;b("toggleBold","Starting"),q(o,"Before");let e=$(T.bold),t=U(o,e);ce(t),P(o,t),q(o,"After")}function me(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.italic),t=U(o,e);P(o,t)}function fe(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.code),t=U(o,e);P(o,t)}function ge(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=$(T.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);P(o,r)}function ve(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.bulletList);ue(o,e)}function ye(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.numberedList);ue(o,e)}function be(o){if(!o||o.disabled||o.readOnly)return;b("toggleQuote","Starting"),q(o,"Initial");let e=$(T.quote),t=V(o,n=>de(n,e),{prefix:e.prefix});ce(t),P(o,t),q(o,"Final")}function J(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.taskList),t=V(o,n=>de(n,e),{prefix:e.prefix});P(o,t)}function Q(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=$(T[n]||T.header1);b("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,c=s;for(;c>0&&r[c-1]!==` +`;)c--;let d=a;for(;d{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):h>0?(b("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=i.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=i.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:i.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let B=Math.max(y-m,x);return b("insertHeader",` - Removing header, adjusting by -${m}`),{start:B,end:y===w?B:Math.max(w-m,x)}}else if(m>0){let B=i.prefix.length-m;return b("insertHeader",` - Replacing header, adjusting by ${B}`),{start:y+B,end:w+B}}else return b("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:y+i.prefix.length,end:w+i.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),P(o,f)}function we(o){Q(o,1,!0)}function xe(o){Q(o,2,!0)}function ke(o){Q(o,3,!0)}function Le(o){return ot(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Le)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` @@ -890,35 +890,35 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! - `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,n=this.findLinkAtPosition(t,e);n?(!this.currentLink||this.currentLink.url!==n.url||this.currentLink.index!==n.index)&&this.show(n):this.scheduleHide()}findLinkAtPosition(e,t){let n=/\[([^\]]+)\]\(([^)]+)\)/g,i,r=0;for(;(i=n.exec(e))!==null;){let s=i.index,a=i.index+i[0].length;if(t>=s&&t<=a)return{text:i[1],url:i[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let n=t.getBoundingClientRect();if(!(n.width===0||n.height===0))try{let{x:i,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${i}px`,top:`${r}px`,position:"absolute"})}catch(i){console.warn("Floating UI positioning failed:",i);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Se=` + `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,n=this.findLinkAtPosition(t,e);n?(!this.currentLink||this.currentLink.url!==n.url||this.currentLink.index!==n.index)&&this.show(n):this.scheduleHide()}findLinkAtPosition(e,t){let n=/\[([^\]]+)\]\(([^)]+)\)/g,i,r=0;for(;(i=n.exec(e))!==null;){let s=i.index,a=i.index+i[0].length;if(t>=s&&t<=a)return{text:i[1],url:i[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let n=t.getBoundingClientRect();if(!(n.width===0||n.height===0))try{let{x:i,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${i}px`,top:`${r}px`,position:"absolute"})}catch(i){console.warn("Floating UI positioning failed:",i);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Ee=` `,Te=` -`,Ee=` - `,Ce=` - + `,Ae=` - + `,Me=` + +`,He=` -`,He=` +`,$e=` -`,$e=` +`,Ie=` -`,Ie=` +`,Be=` @@ -929,7 +929,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! `,Pe=` -`,Be=` +`,_e=` @@ -939,24 +939,24 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! `,Ne=` -`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Se,title:"Bold (Ctrl+B)",action:({editor:o})=>{he(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{ue(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:He,title:"Inline Code",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:Me,title:"Insert Link",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ee,title:"Heading 1",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ce,title:"Heading 2",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Ae,title:"Heading 3",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Ie,title:"Numbered List",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:Be,title:"Task List",action:({editor:o})=>{G&&(G(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},_=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function _e(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function Oe(o){let e=o||_;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function it(o,e){let t=Oe(o),n=Oe(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(m.prototype);return s._init(r,t),r.overTypeInstance=s,m.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++m.instanceCount,this.initialized=!1,m.injectStyles(),m.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new O(this),this._rebuildActionsMap(),this.linkTooltip=new q(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||m.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=N(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||m.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=N(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||_;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=_e(_),this.options.toolbarButtons&&Object.assign(this.actionsById,_e(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tc.replace(/^ /,"")).join(` -`);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+p,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else if(n!==i){let s=r.substring(0,n),a=r.substring(n,i),p=r.substring(i),l=a.split(` -`).map(c=>" "+c).join(` -`);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+p,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else document.execCommand?document.execCommand("insertText",!1," "):(this.textarea.value=r.substring(0,n)+" "+r.substring(i),this.textarea.selectionStart=this.textarea.selectionEnd=n+2);this.textarea.dispatchEvent(new Event("input",{bubbles:!0}));return}if(e.key==="Enter"&&!e.shiftKey&&!e.metaKey&&!e.ctrlKey&&this.options.smartLists&&this.handleSmartListContinuation()){e.preventDefault();return}!this.shortcuts.handleKeydown(e)&&this.options.onKeydown&&this.options.onKeydown(e,this)}handleSmartListContinuation(){let e=this.textarea,t=e.selectionStart,n=S.getListContext(e.value,t);return!n||!n.inList?!1:n.content.trim()===""&&t>=n.markerEndPos?(this.deleteListMarker(n),!0):(t>n.markerEndPos&&t`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Ee,title:"Bold (Ctrl+B)",action:({editor:o})=>{he(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:$e,title:"Inline Code",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ce,title:"Heading 1",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Me,title:"Heading 3",action:({editor:o})=>{ke(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:Ie,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Be,title:"Numbered List",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:_e,title:"Task List",action:({editor:o})=>{J&&(J(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function je(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function ze(o){let e=o||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function rt(o,e){let t=ze(o),n=ze(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(u.prototype);return s._init(r,t),r.overTypeInstance=s,u.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++u.instanceCount,this.initialized=!1,u.injectStyles(),u.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new j(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||u.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=_(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||u.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=_(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=je(N),this.options.toolbarButtons&&Object.assign(this.actionsById,je(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tp.replace(/^ /,"")).join(` +`);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else if(n!==i){let s=r.substring(0,n),a=r.substring(n,i),c=r.substring(i),l=a.split(` +`).map(p=>" "+p).join(` +`);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else document.execCommand?document.execCommand("insertText",!1," "):(this.textarea.value=r.substring(0,n)+" "+r.substring(i),this.textarea.selectionStart=this.textarea.selectionEnd=n+2);this.textarea.dispatchEvent(new Event("input",{bubbles:!0}));return}if(e.key==="Enter"&&!e.shiftKey&&!e.metaKey&&!e.ctrlKey&&this.options.smartLists&&this.handleSmartListContinuation()){e.preventDefault();return}!this.shortcuts.handleKeydown(e)&&this.options.onKeydown&&this.options.onKeydown(e,this)}handleSmartListContinuation(){let e=this.textarea,t=e.selectionStart,n=S.getListContext(e.value,t);return!n||!n.inList?!1:n.content.trim()===""&&t>=n.markerEndPos?(this.deleteListMarker(n),!0):(t>n.markerEndPos&&t{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,n=S.renumberLists(e);if(n!==e){let i=0,r=e.split(` `),s=n.split(` -`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&it(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAutoThemeListener(),this.instanceTheme=e,e==="auto"){this._setupAutoThemeListener();let t=W("auto");this._applyResolvedTheme(t)}else{let t=typeof e=="string"?M(e):e,n=typeof t=="string"?t:t.name;if(n&&this.container.setAttribute("data-theme",n),t&&t.colors){let i=N(t.colors);this.container.style.cssText+=i}this.updatePreview()}return this}_applyResolvedTheme(e){let t=M(e);if(this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t&&t.colors){let n=N(t.colors);this.container.style.cssText+=n}this.updatePreview()}_setupAutoThemeListener(){window.matchMedia&&(this.autoThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.autoThemeListener=e=>{let t=e.matches?"cave":"solar";this._applyResolvedTheme(t)},this.autoThemeMediaQuery.addEventListener?this.autoThemeMediaQuery.addEventListener("change",this.autoThemeListener):this.autoThemeMediaQuery.addListener&&this.autoThemeMediaQuery.addListener(this.autoThemeListener))}_cleanupAutoThemeListener(){this.autoThemeMediaQuery&&this.autoThemeListener&&(this.autoThemeMediaQuery.removeEventListener?this.autoThemeMediaQuery.removeEventListener("change",this.autoThemeListener):this.autoThemeMediaQuery.removeListener&&this.autoThemeMediaQuery.removeListener(this.autoThemeListener),this.autoThemeMediaQuery=null,this.autoThemeListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` +`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&rt(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(K("auto"));else{let t=typeof e=="string"?M(e):e,n=typeof t=="string"?t:t.name;if(n&&this.container.setAttribute("data-theme",n),t&&t.colors){let i=_(t.colors);this.container.style.cssText+=i}this.updatePreview()}return this}_applyTheme(e){let t=M(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}_setupAuto(){window.matchMedia&&(u._autoInstances.add(this),u._mq||(u._mq=window.matchMedia("(prefers-color-scheme: dark)"),u._mqListener=e=>{let t=e.matches?"cave":"solar";u._autoInstances.forEach(n=>n._applyTheme(t))},u._mq.addEventListener?u._mq.addEventListener("change",u._mqListener):u._mq.addListener&&u._mq.addListener(u._mqListener)))}_cleanupAuto(){u._autoInstances.delete(this),u._autoInstances.size===0&&u._mq&&(u._mq.removeEventListener?u._mq.removeEventListener("change",u._mqListener):u._mq.removeListener&&u._mq.removeListener(u._mqListener),u._mq=null,u._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` `),n=e.length,i=e.split(/\s+/).filter(l=>l.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(` -`),p=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:n,words:i,lines:t.length,line:p,column:d}):this.statsBar.innerHTML=` +`),c=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:n,words:i,lines:t.length,line:c,column:d}):this.statsBar.innerHTML=`
    ${n} chars, ${i} words, ${t.length} lines
    -
    Line ${p}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let p=e.scrollHeight;if(this.options.minHeight){let c=parseInt(this.options.minHeight);p=Math.max(p,c)}let d="hidden";if(this.options.maxHeight){let c=parseInt(this.options.maxHeight);p>c&&(p=c,d="auto")}let l=p+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==p&&(this.previousHeight=p)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAutoThemeListener(),this.element.overTypeInstance=null,m.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new m(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let p=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[p]=m._parseDataValue(s.value)}return new m(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||m.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=m.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(m.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=m.currentTheme||A,i=te({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),m.stylesInjected=!0}static setTheme(e,t=null){if(m._cleanupGlobalAutoThemeListener(),e==="auto"){m._setupGlobalAutoThemeListener();let n=W("auto");m._applyGlobalResolvedTheme(n,t)}else{let n=typeof e=="string"?M(e):e;t&&(n=Q(n,t)),m.currentTheme=n,m.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(r=>{let s=typeof n=="string"?n:n.name;s&&r.setAttribute("data-theme",s)}),document.querySelectorAll(".overtype-wrapper").forEach(r=>{if(!r.closest(".overtype-container")){let a=typeof n=="string"?n:n.name;a&&r.setAttribute("data-theme",a)}let s=r._instance;s&&s.updatePreview()});let i=typeof n=="string"?n:n.name;document.querySelectorAll("overtype-editor").forEach(r=>{i&&typeof r.setAttribute=="function"&&r.setAttribute("theme",i),typeof r.refreshTheme=="function"&&r.refreshTheme()})}}static _applyGlobalResolvedTheme(e,t=null){let n=M(e);t&&(n=Q(n,t)),m.currentTheme=n,m.injectStyles(!0),document.querySelectorAll(".overtype-container").forEach(i=>{i.setAttribute("data-theme","auto"),i.setAttribute("data-resolved-theme",e)}),document.querySelectorAll(".overtype-wrapper").forEach(i=>{i.closest(".overtype-container")||(i.setAttribute("data-theme","auto"),i.setAttribute("data-resolved-theme",e));let r=i._instance;r&&r.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(i=>{typeof i.setAttribute=="function"&&(i.setAttribute("theme","auto"),i.setAttribute("data-resolved-theme",e)),typeof i.refreshTheme=="function"&&i.refreshTheme()})}static _setupGlobalAutoThemeListener(){window.matchMedia&&(m.autoThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),m.autoThemeListener=e=>{let t=e.matches?"cave":"solar";m._applyGlobalResolvedTheme(t)},m.autoThemeMediaQuery.addEventListener?m.autoThemeMediaQuery.addEventListener("change",m.autoThemeListener):m.autoThemeMediaQuery.addListener&&m.autoThemeMediaQuery.addListener(m.autoThemeListener))}static _cleanupGlobalAutoThemeListener(){m.autoThemeMediaQuery&&m.autoThemeListener&&(m.autoThemeMediaQuery.removeEventListener?m.autoThemeMediaQuery.removeEventListener("change",m.autoThemeListener):m.autoThemeMediaQuery.removeListener&&m.autoThemeMediaQuery.removeListener(m.autoThemeListener),m.autoThemeMediaQuery=null,m.autoThemeListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){m.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),m.globalListenersInitialized=!0)}};T(m,"instances",new WeakMap),T(m,"stylesInjected",!1),T(m,"globalListenersInitialized",!1),T(m,"instanceCount",0),T(m,"autoThemeMediaQuery",null),T(m,"autoThemeListener",null);var I=m;I.MarkdownParser=S;I.ShortcutsManager=O;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var rt=I;return De(st);})(); +
    Line ${c}, Col ${d}
    + `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,u.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new u(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=u._parseDataValue(s.value)}return new u(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||u.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=u.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(u.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=u.currentTheme||A,i=ne({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),u.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let n=document.querySelectorAll(".overtype-container"),i=document.querySelectorAll(".overtype-wrapper");n.forEach(r=>{t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)}),i.forEach(r=>{var s;r.closest(".overtype-container")||(t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)),(s=r._instance)==null||s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{var s,a,c,d;t?((s=r.setAttribute)==null||s.call(r,"theme","auto"),(a=r.setAttribute)==null||a.call(r,"data-resolved-theme",e)):(c=r.setAttribute)==null||c.call(r,"theme",e),(d=r.refreshTheme)==null||d.call(r)})}static setTheme(e,t=null){if(u._cleanupGlobalAuto(),e==="auto")u._setupGlobalAuto(),u._applyGlobalTheme(K("auto"),t,!0);else{let n=typeof e=="string"?M(e):e;t&&(n=G(n,t)),u.currentTheme=n,u.injectStyles(!0);let i=n.name||e;i&&u._updateThemeAttrs(i)}}static _applyGlobalTheme(e,t=null,n=!1){let i=M(e);t&&(i=G(i,t)),u.currentTheme=i,u.injectStyles(!0),u._updateThemeAttrs(e,n)}static _setupGlobalAuto(){!window.matchMedia||u._globalAutoMq||(u._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),u._globalAutoListener=e=>{u._applyGlobalTheme(e.matches?"cave":"solar",null,!0)},u._globalAutoMq.addEventListener?u._globalAutoMq.addEventListener("change",u._globalAutoListener):u._globalAutoMq.addListener&&u._globalAutoMq.addListener(u._globalAutoListener))}static _cleanupGlobalAuto(){u._globalAutoMq&&u._globalAutoListener&&(u._globalAutoMq.removeEventListener?u._globalAutoMq.removeEventListener("change",u._globalAutoListener):u._globalAutoMq.removeListener&&u._globalAutoMq.removeListener(u._globalAutoListener),u._globalAutoMq=null,u._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){u.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),u.globalListenersInitialized=!0)}};E(u,"instances",new WeakMap),E(u,"stylesInjected",!1),E(u,"globalListenersInitialized",!1),E(u,"instanceCount",0),E(u,"_mq",null),E(u,"_mqListener",null),E(u,"_autoInstances",new Set),E(u,"_globalAutoMq",null),E(u,"_globalAutoListener",null);var I=u;I.MarkdownParser=S;I.ShortcutsManager=j;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var st=I;return De(at);})(); /** * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment * @version 1.0.0 diff --git a/src/overtype.js b/src/overtype.js index d43f28e..38f4a21 100644 --- a/src/overtype.js +++ b/src/overtype.js @@ -80,8 +80,11 @@ class OverType { static stylesInjected = false; static globalListenersInitialized = false; static instanceCount = 0; - static autoThemeMediaQuery = null; // Media query for auto theme switching - static autoThemeListener = null; // Listener function for auto theme changes + static _mq = null; // Shared media query for auto theme + static _mqListener = null; // Shared listener + static _autoInstances = new Set(); // Track auto-themed instances + static _globalAutoMq = null; // Global auto theme media query + static _globalAutoListener = null; // Global auto theme listener /** * Constructor - Always returns an array of instances @@ -1034,17 +1037,16 @@ class OverType { */ setTheme(theme) { // Clean up existing auto theme listener if any - this._cleanupAutoThemeListener(); + this._cleanupAuto(); // Update instance theme this.instanceTheme = theme; // Handle auto theme if (theme === 'auto') { - this._setupAutoThemeListener(); + this._setupAuto(); // Apply the initial resolved theme - const resolvedTheme = resolveAutoTheme('auto'); - this._applyResolvedTheme(resolvedTheme); + this._applyTheme(resolveAutoTheme('auto')); } else { // Get theme object for non-auto themes const themeObj = typeof theme === 'string' ? getTheme(theme) : theme; @@ -1073,7 +1075,7 @@ class OverType { * @private * @param {string} themeName - Resolved theme name */ - _applyResolvedTheme(themeName) { + _applyTheme(themeName) { const themeObj = getTheme(themeName); // Update container with resolved theme, but keep auto in data-theme for tracking @@ -1081,9 +1083,8 @@ class OverType { this.container.setAttribute('data-resolved-theme', themeName); // Apply CSS variables - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj?.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } // Update preview to reflect new theme @@ -1094,21 +1095,26 @@ class OverType { * Setup auto theme listener for instance * @private */ - _setupAutoThemeListener() { + _setupAuto() { if (!window.matchMedia) return; - this.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); - this.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? 'cave' : 'solar'; - this._applyResolvedTheme(resolvedTheme); - }; - - // Use addEventListener if available (modern browsers) - if (this.autoThemeMediaQuery.addEventListener) { - this.autoThemeMediaQuery.addEventListener('change', this.autoThemeListener); - } else if (this.autoThemeMediaQuery.addListener) { - // Fallback for older browsers - this.autoThemeMediaQuery.addListener(this.autoThemeListener); + // Add this instance to the global auto instances set + OverType._autoInstances.add(this); + + // Setup global listener if not already setup + if (!OverType._mq) { + OverType._mq = window.matchMedia('(prefers-color-scheme: dark)'); + OverType._mqListener = (e) => { + const theme = e.matches ? 'cave' : 'solar'; + // Notify all auto-themed instances + OverType._autoInstances.forEach(inst => inst._applyTheme(theme)); + }; + + if (OverType._mq.addEventListener) { + OverType._mq.addEventListener('change', OverType._mqListener); + } else if (OverType._mq.addListener) { + OverType._mq.addListener(OverType._mqListener); + } } } @@ -1116,16 +1122,19 @@ class OverType { * Clean up auto theme listener for instance * @private */ - _cleanupAutoThemeListener() { - if (this.autoThemeMediaQuery && this.autoThemeListener) { - if (this.autoThemeMediaQuery.removeEventListener) { - this.autoThemeMediaQuery.removeEventListener('change', this.autoThemeListener); - } else if (this.autoThemeMediaQuery.removeListener) { - // Fallback for older browsers - this.autoThemeMediaQuery.removeListener(this.autoThemeListener); + _cleanupAuto() { + // Remove this instance from the auto instances set + OverType._autoInstances.delete(this); + + // If no more auto instances, cleanup the global listener + if (OverType._autoInstances.size === 0 && OverType._mq) { + if (OverType._mq.removeEventListener) { + OverType._mq.removeEventListener('change', OverType._mqListener); + } else if (OverType._mq.removeListener) { + OverType._mq.removeListener(OverType._mqListener); } - this.autoThemeMediaQuery = null; - this.autoThemeListener = null; + OverType._mq = null; + OverType._mqListener = null; } } @@ -1335,7 +1344,7 @@ class OverType { */ destroy() { // Clean up auto theme listener - this._cleanupAutoThemeListener(); + this._cleanupAuto(); // Remove instance reference this.element.overTypeInstance = null; @@ -1455,6 +1464,48 @@ class OverType { OverType.stylesInjected = true; } + /** + * Helper to update DOM elements with theme attributes + * @private + */ + static _updateThemeAttrs(themeName, isAuto = false) { + // Single query for containers and wrappers + const containers = document.querySelectorAll('.overtype-container'); + const wrappers = document.querySelectorAll('.overtype-wrapper'); + + containers.forEach(el => { + if (isAuto) { + el.setAttribute('data-theme', 'auto'); + el.setAttribute('data-resolved-theme', themeName); + } else { + el.setAttribute('data-theme', themeName); + } + }); + + wrappers.forEach(wrapper => { + if (!wrapper.closest('.overtype-container')) { + if (isAuto) { + wrapper.setAttribute('data-theme', 'auto'); + wrapper.setAttribute('data-resolved-theme', themeName); + } else { + wrapper.setAttribute('data-theme', themeName); + } + } + wrapper._instance?.updatePreview(); + }); + + // Update web components + document.querySelectorAll('overtype-editor').forEach(wc => { + if (isAuto) { + wc.setAttribute?.('theme', 'auto'); + wc.setAttribute?.('data-resolved-theme', themeName); + } else { + wc.setAttribute?.('theme', themeName); + } + wc.refreshTheme?.(); + }); + } + /** * Set global theme for all OverType instances * @param {string|Object} theme - Theme name or custom theme object @@ -1462,14 +1513,12 @@ class OverType { */ static setTheme(theme, customColors = null) { // Clean up existing auto theme listener - OverType._cleanupGlobalAutoThemeListener(); + OverType._cleanupGlobalAuto(); // Handle auto theme at global level if (theme === 'auto') { - OverType._setupGlobalAutoThemeListener(); - // Apply the initial resolved theme - const resolvedTheme = resolveAutoTheme('auto'); - OverType._applyGlobalResolvedTheme(resolvedTheme, customColors); + OverType._setupGlobalAuto(); + OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true); } else { // Process theme let themeObj = typeof theme === 'string' ? getTheme(theme) : theme; @@ -1485,43 +1534,11 @@ class OverType { // Re-inject styles with new theme OverType.injectStyles(true); - // Update all existing instances - update container theme attribute - document.querySelectorAll('.overtype-container').forEach(container => { - const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; - if (themeName) { - container.setAttribute('data-theme', themeName); - } - }); - - // Also handle any old-style wrappers without containers - document.querySelectorAll('.overtype-wrapper').forEach(wrapper => { - if (!wrapper.closest('.overtype-container')) { - const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; - if (themeName) { - wrapper.setAttribute('data-theme', themeName); - } - } - - // Trigger preview update for the instance - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - - // Update web components (shadow DOM instances) - const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; - document.querySelectorAll('overtype-editor').forEach(webComponent => { - // Set the theme attribute to update the theme name - if (themeName && typeof webComponent.setAttribute === 'function') { - webComponent.setAttribute('theme', themeName); - } - // Also call refreshTheme() to handle cases where the theme name stays the same - // but the theme object's properties have changed - if (typeof webComponent.refreshTheme === 'function') { - webComponent.refreshTheme(); - } - }); + // Update all existing instances + const themeName = themeObj.name || theme; + if (themeName) { + OverType._updateThemeAttrs(themeName); + } } } @@ -1530,8 +1547,9 @@ class OverType { * @private * @param {string} themeName - Resolved theme name * @param {Object} customColors - Optional color overrides + * @param {boolean} isAuto - Whether this is an auto theme */ - static _applyGlobalResolvedTheme(themeName, customColors = null) { + static _applyGlobalTheme(themeName, customColors = null, isAuto = false) { let themeObj = getTheme(themeName); // Apply custom colors if provided @@ -1545,57 +1563,26 @@ class OverType { // Re-inject styles with new theme OverType.injectStyles(true); - // Update all containers with resolved theme, but keep 'auto' for tracking - document.querySelectorAll('.overtype-container').forEach(container => { - container.setAttribute('data-theme', 'auto'); - container.setAttribute('data-resolved-theme', themeName); - }); - - // Also handle any old-style wrappers without containers - document.querySelectorAll('.overtype-wrapper').forEach(wrapper => { - if (!wrapper.closest('.overtype-container')) { - wrapper.setAttribute('data-theme', 'auto'); - wrapper.setAttribute('data-resolved-theme', themeName); - } - - // Trigger preview update for the instance - const instance = wrapper._instance; - if (instance) { - instance.updatePreview(); - } - }); - - // Update web components - document.querySelectorAll('overtype-editor').forEach(webComponent => { - if (typeof webComponent.setAttribute === 'function') { - webComponent.setAttribute('theme', 'auto'); - webComponent.setAttribute('data-resolved-theme', themeName); - } - if (typeof webComponent.refreshTheme === 'function') { - webComponent.refreshTheme(); - } - }); + // Update all elements + OverType._updateThemeAttrs(themeName, isAuto); } /** * Setup global auto theme listener * @private */ - static _setupGlobalAutoThemeListener() { - if (!window.matchMedia) return; + static _setupGlobalAuto() { + if (!window.matchMedia || OverType._globalAutoMq) return; - OverType.autoThemeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); - OverType.autoThemeListener = (event) => { - const resolvedTheme = event.matches ? 'cave' : 'solar'; - OverType._applyGlobalResolvedTheme(resolvedTheme); + OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)'); + OverType._globalAutoListener = (e) => { + OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true); }; - // Use addEventListener if available (modern browsers) - if (OverType.autoThemeMediaQuery.addEventListener) { - OverType.autoThemeMediaQuery.addEventListener('change', OverType.autoThemeListener); - } else if (OverType.autoThemeMediaQuery.addListener) { - // Fallback for older browsers - OverType.autoThemeMediaQuery.addListener(OverType.autoThemeListener); + if (OverType._globalAutoMq.addEventListener) { + OverType._globalAutoMq.addEventListener('change', OverType._globalAutoListener); + } else if (OverType._globalAutoMq.addListener) { + OverType._globalAutoMq.addListener(OverType._globalAutoListener); } } @@ -1603,16 +1590,15 @@ class OverType { * Clean up global auto theme listener * @private */ - static _cleanupGlobalAutoThemeListener() { - if (OverType.autoThemeMediaQuery && OverType.autoThemeListener) { - if (OverType.autoThemeMediaQuery.removeEventListener) { - OverType.autoThemeMediaQuery.removeEventListener('change', OverType.autoThemeListener); - } else if (OverType.autoThemeMediaQuery.removeListener) { - // Fallback for older browsers - OverType.autoThemeMediaQuery.removeListener(OverType.autoThemeListener); + static _cleanupGlobalAuto() { + if (OverType._globalAutoMq && OverType._globalAutoListener) { + if (OverType._globalAutoMq.removeEventListener) { + OverType._globalAutoMq.removeEventListener('change', OverType._globalAutoListener); + } else if (OverType._globalAutoMq.removeListener) { + OverType._globalAutoMq.removeListener(OverType._globalAutoListener); } - OverType.autoThemeMediaQuery = null; - OverType.autoThemeListener = null; + OverType._globalAutoMq = null; + OverType._globalAutoListener = null; } } diff --git a/src/themes.js b/src/themes.js index 9af90c8..30445b5 100644 --- a/src/themes.js +++ b/src/themes.js @@ -117,19 +117,23 @@ export function getTheme(theme) { return theme; } +// Cache media query for auto theme resolution +let _mq = null; + /** * Resolve auto theme to actual theme based on system color scheme preference * @param {string} themeName - Theme name to resolve * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name) */ export function resolveAutoTheme(themeName) { - if (themeName !== 'auto') { - return themeName; + if (themeName !== 'auto') return themeName; + + // Cache media query object + if (!_mq && window.matchMedia) { + _mq = window.matchMedia('(prefers-color-scheme: dark)'); } - - // Check for system dark mode preference - const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; - return isDarkMode ? 'cave' : 'solar'; + + return _mq?.matches ? 'cave' : 'solar'; } /** From c1a8f9daf8384e38840428db824d336c9e5397a5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:28:03 +0000 Subject: [PATCH 5/8] Further optimize listener registration with optional chaining Co-authored-by: dido739 <152557154+dido739@users.noreply.github.com> --- dist/overtype-webcomponent.esm.js | 52 +++++++++++++------------- dist/overtype-webcomponent.js | 52 +++++++++++++------------- dist/overtype-webcomponent.min.js | 4 +- dist/overtype.cjs | 52 +++++++++++++------------- dist/overtype.esm.js | 52 +++++++++++++------------- dist/overtype.esm.js.map | 4 +- dist/overtype.js | 52 +++++++++++++------------- dist/overtype.js.map | 4 +- dist/overtype.min.js | 20 +++++----- src/overtype.js | 62 ++++++++++--------------------- src/themes.js | 7 +++- 11 files changed, 175 insertions(+), 186 deletions(-) diff --git a/dist/overtype-webcomponent.esm.js b/dist/overtype-webcomponent.esm.js index ce5cd5c..2e94000 100644 --- a/dist/overtype-webcomponent.esm.js +++ b/dist/overtype-webcomponent.esm.js @@ -4082,13 +4082,12 @@ var _OverType = class _OverType { this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + const themeName = themeObj.name || theme; if (themeName) { this.container.setAttribute("data-theme", themeName); } - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4097,7 +4096,6 @@ var _OverType = class _OverType { /** * Apply a resolved theme name (used by auto theme) * @private - * @param {string} themeName - Resolved theme name */ _applyTheme(themeName) { const themeObj = getTheme(themeName); @@ -4113,6 +4111,7 @@ var _OverType = class _OverType { * @private */ _setupAuto() { + var _a; if (!window.matchMedia) return; _OverType._autoInstances.add(this); @@ -4122,11 +4121,11 @@ var _OverType = class _OverType { const theme = e.matches ? "cave" : "solar"; _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); }; - if (_OverType._mq.addEventListener) { - _OverType._mq.addEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.addListener) { - _OverType._mq.addListener(_OverType._mqListener); - } + (_a = _OverType._mq.addEventListener || _OverType._mq.addListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); } } /** @@ -4134,13 +4133,14 @@ var _OverType = class _OverType { * @private */ _cleanupAuto() { + var _a; _OverType._autoInstances.delete(this); if (_OverType._autoInstances.size === 0 && _OverType._mq) { - if (_OverType._mq.removeEventListener) { - _OverType._mq.removeEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.removeListener) { - _OverType._mq.removeListener(_OverType._mqListener); - } + (_a = _OverType._mq.removeEventListener || _OverType._mq.removeListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); _OverType._mq = null; _OverType._mqListener = null; } @@ -4479,29 +4479,31 @@ var _OverType = class _OverType { * @private */ static _setupGlobalAuto() { + var _a; if (!window.matchMedia || _OverType._globalAutoMq) return; _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); _OverType._globalAutoListener = (e) => { _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType._globalAutoMq.addEventListener) { - _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.addListener) { - _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.addEventListener || _OverType._globalAutoMq.addListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); } /** * Clean up global auto theme listener * @private */ static _cleanupGlobalAuto() { + var _a; if (_OverType._globalAutoMq && _OverType._globalAutoListener) { - if (_OverType._globalAutoMq.removeEventListener) { - _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.removeListener) { - _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.removeEventListener || _OverType._globalAutoMq.removeListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); _OverType._globalAutoMq = null; _OverType._globalAutoListener = null; } diff --git a/dist/overtype-webcomponent.js b/dist/overtype-webcomponent.js index 0f51d43..c1858f6 100644 --- a/dist/overtype-webcomponent.js +++ b/dist/overtype-webcomponent.js @@ -4105,13 +4105,12 @@ ${blockSuffix}` : suffix; this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + const themeName = themeObj.name || theme; if (themeName) { this.container.setAttribute("data-theme", themeName); } - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4120,7 +4119,6 @@ ${blockSuffix}` : suffix; /** * Apply a resolved theme name (used by auto theme) * @private - * @param {string} themeName - Resolved theme name */ _applyTheme(themeName) { const themeObj = getTheme(themeName); @@ -4136,6 +4134,7 @@ ${blockSuffix}` : suffix; * @private */ _setupAuto() { + var _a; if (!window.matchMedia) return; _OverType._autoInstances.add(this); @@ -4145,11 +4144,11 @@ ${blockSuffix}` : suffix; const theme = e.matches ? "cave" : "solar"; _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); }; - if (_OverType._mq.addEventListener) { - _OverType._mq.addEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.addListener) { - _OverType._mq.addListener(_OverType._mqListener); - } + (_a = _OverType._mq.addEventListener || _OverType._mq.addListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); } } /** @@ -4157,13 +4156,14 @@ ${blockSuffix}` : suffix; * @private */ _cleanupAuto() { + var _a; _OverType._autoInstances.delete(this); if (_OverType._autoInstances.size === 0 && _OverType._mq) { - if (_OverType._mq.removeEventListener) { - _OverType._mq.removeEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.removeListener) { - _OverType._mq.removeListener(_OverType._mqListener); - } + (_a = _OverType._mq.removeEventListener || _OverType._mq.removeListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); _OverType._mq = null; _OverType._mqListener = null; } @@ -4502,29 +4502,31 @@ ${blockSuffix}` : suffix; * @private */ static _setupGlobalAuto() { + var _a; if (!window.matchMedia || _OverType._globalAutoMq) return; _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); _OverType._globalAutoListener = (e) => { _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType._globalAutoMq.addEventListener) { - _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.addListener) { - _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.addEventListener || _OverType._globalAutoMq.addListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); } /** * Clean up global auto theme listener * @private */ static _cleanupGlobalAuto() { + var _a; if (_OverType._globalAutoMq && _OverType._globalAutoListener) { - if (_OverType._globalAutoMq.removeEventListener) { - _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.removeListener) { - _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.removeEventListener || _OverType._globalAutoMq.removeListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); _OverType._globalAutoMq = null; _OverType._globalAutoListener = null; } diff --git a/dist/overtype-webcomponent.min.js b/dist/overtype-webcomponent.min.js index 5ab20ab..2658e96 100644 --- a/dist/overtype-webcomponent.min.js +++ b/dist/overtype-webcomponent.min.js @@ -948,7 +948,7 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! `+t),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}splitListItem(e,t){let i=e.content.substring(t-e.markerEndPos);this.textarea.setSelectionRange(t,e.lineEnd),document.execCommand("delete");let o=S.createNewListItem(e);document.execCommand("insertText",!1,` `+o+i);let r=this.textarea.selectionStart-i.length;this.textarea.setSelectionRange(r,r),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}scheduleNumberedListUpdate(){this.numberUpdateTimeout&&clearTimeout(this.numberUpdateTimeout),this.numberUpdateTimeout=setTimeout(()=>{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,i=S.renumberLists(e);if(i!==e){let o=0,r=e.split(` `),s=i.split(` -`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),i=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(i=i.replace(/.*?<\/span>/g,""),i=i.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),i=i.replace(/\sclass=""/g,"")),i}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var o;let t=(o=this.options)==null?void 0:o.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let i=this.toolbar&&this.options.toolbar&<(t,this.options.toolbarButtons);this._rebuildActionsMap(),i&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(Z("auto"));else{let t=typeof e=="string"?_(e):e,i=typeof t=="string"?t:t.name;if(i&&this.container.setAttribute("data-theme",i),t&&t.colors){let o=B(t.colors);this.container.style.cssText+=o}this.updatePreview()}return this}_applyTheme(e){let t=_(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=B(t.colors)),this.updatePreview()}_setupAuto(){window.matchMedia&&(h._autoInstances.add(this),h._mq||(h._mq=window.matchMedia("(prefers-color-scheme: dark)"),h._mqListener=e=>{let t=e.matches?"cave":"solar";h._autoInstances.forEach(i=>i._applyTheme(t))},h._mq.addEventListener?h._mq.addEventListener("change",h._mqListener):h._mq.addListener&&h._mq.addListener(h._mqListener)))}_cleanupAuto(){h._autoInstances.delete(this),h._autoInstances.size===0&&h._mq&&(h._mq.removeEventListener?h._mq.removeEventListener("change",h._mqListener):h._mq.removeListener&&h._mq.removeListener(h._mqListener),h._mq=null,h._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` +`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),i=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(i=i.replace(/.*?<\/span>/g,""),i=i.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),i=i.replace(/\sclass=""/g,"")),i}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var o;let t=(o=this.options)==null?void 0:o.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let i=this.toolbar&&this.options.toolbar&<(t,this.options.toolbarButtons);this._rebuildActionsMap(),i&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(Z("auto"));else{let t=typeof e=="string"?_(e):e,i=t.name||e;i&&this.container.setAttribute("data-theme",i),t!=null&&t.colors&&(this.container.style.cssText+=B(t.colors)),this.updatePreview()}return this}_applyTheme(e){let t=_(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=B(t.colors)),this.updatePreview()}_setupAuto(){var e;window.matchMedia&&(h._autoInstances.add(this),h._mq||(h._mq=window.matchMedia("(prefers-color-scheme: dark)"),h._mqListener=t=>{let i=t.matches?"cave":"solar";h._autoInstances.forEach(o=>o._applyTheme(i))},(e=h._mq.addEventListener||h._mq.addListener)==null||e.call(h._mq,"change",h._mqListener)))}_cleanupAuto(){var e;h._autoInstances.delete(this),h._autoInstances.size===0&&h._mq&&((e=h._mq.removeEventListener||h._mq.removeListener)==null||e.call(h._mq,"change",h._mqListener),h._mq=null,h._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` `),i=e.length,o=e.split(/\s+/).filter(l=>l.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(` `),c=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:i,words:o,lines:t.length,line:c,column:d}):this.statsBar.innerHTML=`
    @@ -956,7 +956,7 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! ${i} chars, ${o} words, ${t.length} lines
    Line ${c}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper,o=window.getComputedStyle(e),r=parseFloat(o.paddingTop),s=parseFloat(o.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,h.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new h(e,t)}static initFromData(e,t={}){let i=document.querySelectorAll(e);return Array.from(i).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=h._parseDataValue(s.value)}return new h(o,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||h.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=h.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(h.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=h.currentTheme||A,o=R({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),h.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let i=document.querySelectorAll(".overtype-container"),o=document.querySelectorAll(".overtype-wrapper");i.forEach(r=>{t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)}),o.forEach(r=>{var s;r.closest(".overtype-container")||(t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)),(s=r._instance)==null||s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{var s,a,c,d;t?((s=r.setAttribute)==null||s.call(r,"theme","auto"),(a=r.setAttribute)==null||a.call(r,"data-resolved-theme",e)):(c=r.setAttribute)==null||c.call(r,"theme",e),(d=r.refreshTheme)==null||d.call(r)})}static setTheme(e,t=null){if(h._cleanupGlobalAuto(),e==="auto")h._setupGlobalAuto(),h._applyGlobalTheme(Z("auto"),t,!0);else{let i=typeof e=="string"?_(e):e;t&&(i=J(i,t)),h.currentTheme=i,h.injectStyles(!0);let o=i.name||e;o&&h._updateThemeAttrs(o)}}static _applyGlobalTheme(e,t=null,i=!1){let o=_(e);t&&(o=J(o,t)),h.currentTheme=o,h.injectStyles(!0),h._updateThemeAttrs(e,i)}static _setupGlobalAuto(){!window.matchMedia||h._globalAutoMq||(h._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),h._globalAutoListener=e=>{h._applyGlobalTheme(e.matches?"cave":"solar",null,!0)},h._globalAutoMq.addEventListener?h._globalAutoMq.addEventListener("change",h._globalAutoListener):h._globalAutoMq.addListener&&h._globalAutoMq.addListener(h._globalAutoListener))}static _cleanupGlobalAuto(){h._globalAutoMq&&h._globalAutoListener&&(h._globalAutoMq.removeEventListener?h._globalAutoMq.removeEventListener("change",h._globalAutoListener):h._globalAutoMq.removeListener&&h._globalAutoMq.removeListener(h._globalAutoListener),h._globalAutoMq=null,h._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static initGlobalListeners(){h.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let i=t.closest(".overtype-wrapper"),o=i==null?void 0:i._instance;o&&(o.options.showStats&&o.statsBar&&o._updateStats(),clearTimeout(o._selectionTimeout),o._selectionTimeout=setTimeout(()=>{o.updatePreview()},50))}}),h.globalListenersInitialized=!0)}};E(h,"instances",new WeakMap),E(h,"stylesInjected",!1),E(h,"globalListenersInitialized",!1),E(h,"instanceCount",0),E(h,"_mq",null),E(h,"_mqListener",null),E(h,"_autoInstances",new Set),E(h,"_globalAutoMq",null),E(h,"_globalAutoListener",null);var P=h;P.MarkdownParser=S;P.ShortcutsManager=z;P.themes={solar:A,cave:_("cave")};P.getTheme=_;P.currentTheme=A;var Fe=P;var Re="overtype-webcomponent-container",ct="Start typing...",pt=["value","theme","toolbar","height","min-height","max-height","placeholder","font-size","line-height","padding","auto-resize","autofocus","show-stats","smart-lists","readonly"],G=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._editor=null,this._initialized=!1,this._pendingOptions={},this._styleVersion=0,this._baseStyleElement=null,this._selectionChangeHandler=null,this._isConnected=!1,this._handleChange=this._handleChange.bind(this),this._handleKeydown=this._handleKeydown.bind(this)}_decodeValue(e){return typeof e!="string"?"":e.replace(/\\r/g,"\r").replace(/\\n/g,` + `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper,o=window.getComputedStyle(e),r=parseFloat(o.paddingTop),s=parseFloat(o.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,h.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new h(e,t)}static initFromData(e,t={}){let i=document.querySelectorAll(e);return Array.from(i).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=h._parseDataValue(s.value)}return new h(o,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||h.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=h.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(h.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=h.currentTheme||A,o=R({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),h.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let i=document.querySelectorAll(".overtype-container"),o=document.querySelectorAll(".overtype-wrapper");i.forEach(r=>{t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)}),o.forEach(r=>{var s;r.closest(".overtype-container")||(t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)),(s=r._instance)==null||s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{var s,a,c,d;t?((s=r.setAttribute)==null||s.call(r,"theme","auto"),(a=r.setAttribute)==null||a.call(r,"data-resolved-theme",e)):(c=r.setAttribute)==null||c.call(r,"theme",e),(d=r.refreshTheme)==null||d.call(r)})}static setTheme(e,t=null){if(h._cleanupGlobalAuto(),e==="auto")h._setupGlobalAuto(),h._applyGlobalTheme(Z("auto"),t,!0);else{let i=typeof e=="string"?_(e):e;t&&(i=J(i,t)),h.currentTheme=i,h.injectStyles(!0);let o=i.name||e;o&&h._updateThemeAttrs(o)}}static _applyGlobalTheme(e,t=null,i=!1){let o=_(e);t&&(o=J(o,t)),h.currentTheme=o,h.injectStyles(!0),h._updateThemeAttrs(e,i)}static _setupGlobalAuto(){var e;!window.matchMedia||h._globalAutoMq||(h._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),h._globalAutoListener=t=>{h._applyGlobalTheme(t.matches?"cave":"solar",null,!0)},(e=h._globalAutoMq.addEventListener||h._globalAutoMq.addListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener))}static _cleanupGlobalAuto(){var e;h._globalAutoMq&&h._globalAutoListener&&((e=h._globalAutoMq.removeEventListener||h._globalAutoMq.removeListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener),h._globalAutoMq=null,h._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static initGlobalListeners(){h.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let i=t.closest(".overtype-wrapper"),o=i==null?void 0:i._instance;o&&(o.options.showStats&&o.statsBar&&o._updateStats(),clearTimeout(o._selectionTimeout),o._selectionTimeout=setTimeout(()=>{o.updatePreview()},50))}}),h.globalListenersInitialized=!0)}};E(h,"instances",new WeakMap),E(h,"stylesInjected",!1),E(h,"globalListenersInitialized",!1),E(h,"instanceCount",0),E(h,"_mq",null),E(h,"_mqListener",null),E(h,"_autoInstances",new Set),E(h,"_globalAutoMq",null),E(h,"_globalAutoListener",null);var P=h;P.MarkdownParser=S;P.ShortcutsManager=z;P.themes={solar:A,cave:_("cave")};P.getTheme=_;P.currentTheme=A;var Fe=P;var Re="overtype-webcomponent-container",ct="Start typing...",pt=["value","theme","toolbar","height","min-height","max-height","placeholder","font-size","line-height","padding","auto-resize","autofocus","show-stats","smart-lists","readonly"],G=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._editor=null,this._initialized=!1,this._pendingOptions={},this._styleVersion=0,this._baseStyleElement=null,this._selectionChangeHandler=null,this._isConnected=!1,this._handleChange=this._handleChange.bind(this),this._handleKeydown=this._handleKeydown.bind(this)}_decodeValue(e){return typeof e!="string"?"":e.replace(/\\r/g,"\r").replace(/\\n/g,` `).replace(/\\t/g," ")}static get observedAttributes(){return pt}connectedCallback(){this._isConnected=!0,this._initializeEditor()}disconnectedCallback(){this._isConnected=!1,this._cleanup()}attributeChangedCallback(e,t,i){if(t!==i&&!this._silentUpdate){if(!this._initialized){this._pendingOptions[e]=i;return}this._updateOption(e,i)}}_initializeEditor(){if(!(this._initialized||!this._isConnected))try{let e=document.createElement("div");e.className=Re;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");t&&(e.style.height=t),i&&(e.style.minHeight=i),o&&(e.style.maxHeight=o),this._injectStyles(),this.shadowRoot.appendChild(e);let r=this._getOptionsFromAttributes(),s=new Fe(e,r);this._editor=s[0],this._initialized=!0,this._editor&&this._editor.textarea&&(this._editor.textarea.addEventListener("scroll",()=>{this._editor&&this._editor.preview&&this._editor.textarea&&(this._editor.preview.scrollTop=this._editor.textarea.scrollTop,this._editor.preview.scrollLeft=this._editor.textarea.scrollLeft)}),this._editor.textarea.addEventListener("input",a=>{this._editor&&this._editor.handleInput&&this._editor.handleInput(a)}),this._editor.textarea.addEventListener("keydown",a=>{this._editor&&this._editor.handleKeydown&&this._editor.handleKeydown(a)}),this._selectionChangeHandler=()=>{if(document.activeElement===this){let a=this.shadowRoot.activeElement;a&&a===this._editor.textarea&&(this._editor.options.showStats&&this._editor.statsBar&&this._editor._updateStats(),this._editor.linkTooltip&&this._editor.linkTooltip.checkCursorPosition&&this._editor.linkTooltip.checkCursorPosition())}},document.addEventListener("selectionchange",this._selectionChangeHandler)),this._applyPendingOptions(),this._dispatchEvent("ready",{editor:this._editor})}catch(e){let t=e&&e.message?e.message:String(e);console.warn("OverType Web Component initialization failed:",t),this._dispatchEvent("error",{error:{message:t}})}}_injectStyles(){let e=document.createElement("style"),t=this.getAttribute("theme")||"solar",i=_(t),o=this._getOptionsFromAttributes(),r=R({...o,theme:i}),s=` /* Web Component Host Styles */ :host { diff --git a/dist/overtype.cjs b/dist/overtype.cjs index 89c9acf..8e06b05 100644 --- a/dist/overtype.cjs +++ b/dist/overtype.cjs @@ -4108,13 +4108,12 @@ var _OverType = class _OverType { this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + const themeName = themeObj.name || theme; if (themeName) { this.container.setAttribute("data-theme", themeName); } - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4123,7 +4122,6 @@ var _OverType = class _OverType { /** * Apply a resolved theme name (used by auto theme) * @private - * @param {string} themeName - Resolved theme name */ _applyTheme(themeName) { const themeObj = getTheme(themeName); @@ -4139,6 +4137,7 @@ var _OverType = class _OverType { * @private */ _setupAuto() { + var _a; if (!window.matchMedia) return; _OverType._autoInstances.add(this); @@ -4148,11 +4147,11 @@ var _OverType = class _OverType { const theme = e.matches ? "cave" : "solar"; _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); }; - if (_OverType._mq.addEventListener) { - _OverType._mq.addEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.addListener) { - _OverType._mq.addListener(_OverType._mqListener); - } + (_a = _OverType._mq.addEventListener || _OverType._mq.addListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); } } /** @@ -4160,13 +4159,14 @@ var _OverType = class _OverType { * @private */ _cleanupAuto() { + var _a; _OverType._autoInstances.delete(this); if (_OverType._autoInstances.size === 0 && _OverType._mq) { - if (_OverType._mq.removeEventListener) { - _OverType._mq.removeEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.removeListener) { - _OverType._mq.removeListener(_OverType._mqListener); - } + (_a = _OverType._mq.removeEventListener || _OverType._mq.removeListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); _OverType._mq = null; _OverType._mqListener = null; } @@ -4505,29 +4505,31 @@ var _OverType = class _OverType { * @private */ static _setupGlobalAuto() { + var _a; if (!window.matchMedia || _OverType._globalAutoMq) return; _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); _OverType._globalAutoListener = (e) => { _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType._globalAutoMq.addEventListener) { - _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.addListener) { - _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.addEventListener || _OverType._globalAutoMq.addListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); } /** * Clean up global auto theme listener * @private */ static _cleanupGlobalAuto() { + var _a; if (_OverType._globalAutoMq && _OverType._globalAutoListener) { - if (_OverType._globalAutoMq.removeEventListener) { - _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.removeListener) { - _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.removeEventListener || _OverType._globalAutoMq.removeListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); _OverType._globalAutoMq = null; _OverType._globalAutoListener = null; } diff --git a/dist/overtype.esm.js b/dist/overtype.esm.js index 7e61504..1107637 100644 --- a/dist/overtype.esm.js +++ b/dist/overtype.esm.js @@ -4082,13 +4082,12 @@ var _OverType = class _OverType { this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + const themeName = themeObj.name || theme; if (themeName) { this.container.setAttribute("data-theme", themeName); } - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4097,7 +4096,6 @@ var _OverType = class _OverType { /** * Apply a resolved theme name (used by auto theme) * @private - * @param {string} themeName - Resolved theme name */ _applyTheme(themeName) { const themeObj = getTheme(themeName); @@ -4113,6 +4111,7 @@ var _OverType = class _OverType { * @private */ _setupAuto() { + var _a; if (!window.matchMedia) return; _OverType._autoInstances.add(this); @@ -4122,11 +4121,11 @@ var _OverType = class _OverType { const theme = e.matches ? "cave" : "solar"; _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); }; - if (_OverType._mq.addEventListener) { - _OverType._mq.addEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.addListener) { - _OverType._mq.addListener(_OverType._mqListener); - } + (_a = _OverType._mq.addEventListener || _OverType._mq.addListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); } } /** @@ -4134,13 +4133,14 @@ var _OverType = class _OverType { * @private */ _cleanupAuto() { + var _a; _OverType._autoInstances.delete(this); if (_OverType._autoInstances.size === 0 && _OverType._mq) { - if (_OverType._mq.removeEventListener) { - _OverType._mq.removeEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.removeListener) { - _OverType._mq.removeListener(_OverType._mqListener); - } + (_a = _OverType._mq.removeEventListener || _OverType._mq.removeListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); _OverType._mq = null; _OverType._mqListener = null; } @@ -4479,29 +4479,31 @@ var _OverType = class _OverType { * @private */ static _setupGlobalAuto() { + var _a; if (!window.matchMedia || _OverType._globalAutoMq) return; _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); _OverType._globalAutoListener = (e) => { _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType._globalAutoMq.addEventListener) { - _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.addListener) { - _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.addEventListener || _OverType._globalAutoMq.addListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); } /** * Clean up global auto theme listener * @private */ static _cleanupGlobalAuto() { + var _a; if (_OverType._globalAutoMq && _OverType._globalAutoListener) { - if (_OverType._globalAutoMq.removeEventListener) { - _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.removeListener) { - _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.removeEventListener || _OverType._globalAutoMq.removeListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); _OverType._globalAutoMq = null; _OverType._globalAutoListener = null; } diff --git a/dist/overtype.esm.js.map b/dist/overtype.esm.js.map index 44e257b..e12ecfc 100644 --- a/dist/overtype.esm.js.map +++ b/dist/overtype.esm.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js", "../src/overtype.js"], - "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `[${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Clean up existing auto theme listener if any\n      this._cleanupAuto();\n\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Handle auto theme\n      if (theme === 'auto') {\n        this._setupAuto();\n        // Apply the initial resolved theme\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        // Get theme object for non-auto themes\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n        // Update container theme attribute\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        // Apply CSS variables to container for instance override\n        if (themeObj && themeObj.colors) {\n          const cssVars = themeToCSSVars(themeObj.colors);\n          this.container.style.cssText += cssVars;\n        }\n\n        // Update preview to reflect new theme\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     * @param {string} themeName - Resolved theme name\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      \n      // Update container with resolved theme, but keep auto in data-theme for tracking\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      // Apply CSS variables\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      // Add this instance to the global auto instances set\n      OverType._autoInstances.add(this);\n\n      // Setup global listener if not already setup\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          // Notify all auto-themed instances\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        if (OverType._mq.addEventListener) {\n          OverType._mq.addEventListener('change', OverType._mqListener);\n        } else if (OverType._mq.addListener) {\n          OverType._mq.addListener(OverType._mqListener);\n        }\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      // Remove this instance from the auto instances set\n      OverType._autoInstances.delete(this);\n\n      // If no more auto instances, cleanup the global listener\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        if (OverType._mq.removeEventListener) {\n          OverType._mq.removeEventListener('change', OverType._mqListener);\n        } else if (OverType._mq.removeListener) {\n          OverType._mq.removeListener(OverType._mqListener);\n        }\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n // Single query for containers and wrappers\n const containers = document.querySelectorAll('.overtype-container');\n const wrappers = document.querySelectorAll('.overtype-wrapper');\n \n containers.forEach(el => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n });\n \n wrappers.forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n if (isAuto) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n } else {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n wrapper._instance?.updatePreview();\n });\n \n // Update web components\n document.querySelectorAll('overtype-editor').forEach(wc => {\n if (isAuto) {\n wc.setAttribute?.('theme', 'auto');\n wc.setAttribute?.('data-resolved-theme', themeName);\n } else {\n wc.setAttribute?.('theme', themeName);\n }\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n if (OverType._globalAutoMq.addEventListener) {\n OverType._globalAutoMq.addEventListener('change', OverType._globalAutoListener);\n } else if (OverType._globalAutoMq.addListener) {\n OverType._globalAutoMq.addListener(OverType._globalAutoListener);\n }\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n if (OverType._globalAutoMq.removeEventListener) {\n OverType._globalAutoMq.removeEventListener('change', OverType._globalAutoListener);\n } else if (OverType._globalAutoMq.removeListener) {\n OverType._globalAutoMq.removeListener(OverType._globalAutoListener);\n }\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], - "mappings": "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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;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", + "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n // Single query for containers and wrappers\n const containers = document.querySelectorAll('.overtype-container');\n const wrappers = document.querySelectorAll('.overtype-wrapper');\n \n containers.forEach(el => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n });\n \n wrappers.forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n if (isAuto) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n } else {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n wrapper._instance?.updatePreview();\n });\n \n // Update web components\n document.querySelectorAll('overtype-editor').forEach(wc => {\n if (isAuto) {\n wc.setAttribute?.('theme', 'auto');\n wc.setAttribute?.('data-resolved-theme', themeName);\n } else {\n wc.setAttribute?.('theme', themeName);\n }\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], + "mappings": "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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons"] } diff --git a/dist/overtype.js b/dist/overtype.js index 9795e3b..b66d407 100644 --- a/dist/overtype.js +++ b/dist/overtype.js @@ -4108,13 +4108,12 @@ ${blockSuffix}` : suffix; this._applyTheme(resolveAutoTheme("auto")); } else { const themeObj = typeof theme === "string" ? getTheme(theme) : theme; - const themeName = typeof themeObj === "string" ? themeObj : themeObj.name; + const themeName = themeObj.name || theme; if (themeName) { this.container.setAttribute("data-theme", themeName); } - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj == null ? void 0 : themeObj.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } this.updatePreview(); } @@ -4123,7 +4122,6 @@ ${blockSuffix}` : suffix; /** * Apply a resolved theme name (used by auto theme) * @private - * @param {string} themeName - Resolved theme name */ _applyTheme(themeName) { const themeObj = getTheme(themeName); @@ -4139,6 +4137,7 @@ ${blockSuffix}` : suffix; * @private */ _setupAuto() { + var _a; if (!window.matchMedia) return; _OverType._autoInstances.add(this); @@ -4148,11 +4147,11 @@ ${blockSuffix}` : suffix; const theme = e.matches ? "cave" : "solar"; _OverType._autoInstances.forEach((inst) => inst._applyTheme(theme)); }; - if (_OverType._mq.addEventListener) { - _OverType._mq.addEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.addListener) { - _OverType._mq.addListener(_OverType._mqListener); - } + (_a = _OverType._mq.addEventListener || _OverType._mq.addListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); } } /** @@ -4160,13 +4159,14 @@ ${blockSuffix}` : suffix; * @private */ _cleanupAuto() { + var _a; _OverType._autoInstances.delete(this); if (_OverType._autoInstances.size === 0 && _OverType._mq) { - if (_OverType._mq.removeEventListener) { - _OverType._mq.removeEventListener("change", _OverType._mqListener); - } else if (_OverType._mq.removeListener) { - _OverType._mq.removeListener(_OverType._mqListener); - } + (_a = _OverType._mq.removeEventListener || _OverType._mq.removeListener) == null ? void 0 : _a.call( + _OverType._mq, + "change", + _OverType._mqListener + ); _OverType._mq = null; _OverType._mqListener = null; } @@ -4505,29 +4505,31 @@ ${blockSuffix}` : suffix; * @private */ static _setupGlobalAuto() { + var _a; if (!window.matchMedia || _OverType._globalAutoMq) return; _OverType._globalAutoMq = window.matchMedia("(prefers-color-scheme: dark)"); _OverType._globalAutoListener = (e) => { _OverType._applyGlobalTheme(e.matches ? "cave" : "solar", null, true); }; - if (_OverType._globalAutoMq.addEventListener) { - _OverType._globalAutoMq.addEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.addListener) { - _OverType._globalAutoMq.addListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.addEventListener || _OverType._globalAutoMq.addListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); } /** * Clean up global auto theme listener * @private */ static _cleanupGlobalAuto() { + var _a; if (_OverType._globalAutoMq && _OverType._globalAutoListener) { - if (_OverType._globalAutoMq.removeEventListener) { - _OverType._globalAutoMq.removeEventListener("change", _OverType._globalAutoListener); - } else if (_OverType._globalAutoMq.removeListener) { - _OverType._globalAutoMq.removeListener(_OverType._globalAutoListener); - } + (_a = _OverType._globalAutoMq.removeEventListener || _OverType._globalAutoMq.removeListener) == null ? void 0 : _a.call( + _OverType._globalAutoMq, + "change", + _OverType._globalAutoListener + ); _OverType._globalAutoMq = null; _OverType._globalAutoListener = null; } diff --git a/dist/overtype.js.map b/dist/overtype.js.map index 7f18047..e59af0c 100644 --- a/dist/overtype.js.map +++ b/dist/overtype.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/overtype.js", "../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js"], - "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      // Clean up existing auto theme listener if any\n      this._cleanupAuto();\n\n      // Update instance theme\n      this.instanceTheme = theme;\n\n      // Handle auto theme\n      if (theme === 'auto') {\n        this._setupAuto();\n        // Apply the initial resolved theme\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        // Get theme object for non-auto themes\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name;\n\n        // Update container theme attribute\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        // Apply CSS variables to container for instance override\n        if (themeObj && themeObj.colors) {\n          const cssVars = themeToCSSVars(themeObj.colors);\n          this.container.style.cssText += cssVars;\n        }\n\n        // Update preview to reflect new theme\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     * @param {string} themeName - Resolved theme name\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      \n      // Update container with resolved theme, but keep auto in data-theme for tracking\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      // Apply CSS variables\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      // Update preview to reflect new theme\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      // Add this instance to the global auto instances set\n      OverType._autoInstances.add(this);\n\n      // Setup global listener if not already setup\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          // Notify all auto-themed instances\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        if (OverType._mq.addEventListener) {\n          OverType._mq.addEventListener('change', OverType._mqListener);\n        } else if (OverType._mq.addListener) {\n          OverType._mq.addListener(OverType._mqListener);\n        }\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      // Remove this instance from the auto instances set\n      OverType._autoInstances.delete(this);\n\n      // If no more auto instances, cleanup the global listener\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        if (OverType._mq.removeEventListener) {\n          OverType._mq.removeEventListener('change', OverType._mqListener);\n        } else if (OverType._mq.removeListener) {\n          OverType._mq.removeListener(OverType._mqListener);\n        }\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n // Single query for containers and wrappers\n const containers = document.querySelectorAll('.overtype-container');\n const wrappers = document.querySelectorAll('.overtype-wrapper');\n \n containers.forEach(el => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n });\n \n wrappers.forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n if (isAuto) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n } else {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n wrapper._instance?.updatePreview();\n });\n \n // Update web components\n document.querySelectorAll('overtype-editor').forEach(wc => {\n if (isAuto) {\n wc.setAttribute?.('theme', 'auto');\n wc.setAttribute?.('data-resolved-theme', themeName);\n } else {\n wc.setAttribute?.('theme', themeName);\n }\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n if (OverType._globalAutoMq.addEventListener) {\n OverType._globalAutoMq.addEventListener('change', OverType._globalAutoListener);\n } else if (OverType._globalAutoMq.addListener) {\n OverType._globalAutoMq.addListener(OverType._globalAutoListener);\n }\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n if (OverType._globalAutoMq.removeEventListener) {\n OverType._globalAutoMq.removeEventListener('change', OverType._globalAutoListener);\n } else if (OverType._globalAutoMq.removeListener) {\n OverType._globalAutoMq.removeListener(OverType._globalAutoListener);\n }\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n return isDarkMode ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], - "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQO,MAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA,IAa1B,OAAO,iBAAiB;AACtB,WAAK,YAAY;AAAA,IACnB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,mBAAmB,aAAa;AACrC,WAAK,kBAAkB;AAAA,IACzB;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,gBAAgB,WAAW;AAChC,WAAK,eAAe;AAAA,IACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,kBAAkB,MAAM;AAC7B,UAAI,KAAK,cAAc;AACrB,eAAO,KAAK,aAAa,IAAI;AAAA,MAC/B;AACA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,WAAW,MAAM;AACtB,YAAM,MAAM;AAAA,QACV,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA,aAAO,KAAK,QAAQ,YAAY,OAAK,IAAI,CAAC,CAAC;AAAA,IAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,OAAO,oBAAoB,MAAM,cAAc;AAC7C,YAAM,gBAAgB,aAAa,MAAM,QAAQ,EAAE,CAAC;AACpD,YAAM,cAAc,cAAc,QAAQ,MAAM,QAAQ;AACxD,aAAO,KAAK,QAAQ,QAAQ,WAAW;AAAA,IACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,YAAY,MAAM;AACvB,aAAO,KAAK,QAAQ,oBAAoB,CAAC,OAAO,QAAQ,YAAY;AAClE,cAAM,QAAQ,OAAO;AACrB,eAAO,KAAK,KAAK,gCAAgC,MAAM,WAAW,OAAO,MAAM,KAAK;AAAA,MACtF,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,oBAAoB,MAAM;AAC/B,UAAI,KAAK,MAAM,wBAAwB,GAAG;AACxC,eAAO,gCAAgC,IAAI;AAAA,MAC7C;AACA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,gBAAgB,MAAM;AAC3B,aAAO,KAAK,QAAQ,eAAe,CAAC,OAAO,YAAY;AACrD,eAAO,oEAAoE,OAAO;AAAA,MACpF,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,gBAAgB,MAAM;AAC3B,aAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,eAAO,GAAG,MAAM,uDAAuD,MAAM,WAAW,OAAO;AAAA,MACjG,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,OAAO,cAAc,MAAM,gBAAgB,OAAO;AAChD,aAAO,KAAK,QAAQ,yCAAyC,CAAC,OAAO,QAAQ,SAAS,YAAY;AAChG,YAAI,eAAe;AAEjB,gBAAM,YAAY,QAAQ,YAAY,MAAM;AAC5C,iBAAO,GAAG,MAAM,gDAAgD,YAAY,YAAY,EAAE,KAAK,OAAO;AAAA,QACxG,OAAO;AAEL,iBAAO,GAAG,MAAM,wDAAwD,OAAO,YAAY,OAAO;AAAA,QACpG;AAAA,MACF,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,kBAAkB,MAAM;AAC7B,aAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,eAAO,GAAG,MAAM,wDAAwD,MAAM,WAAW,OAAO;AAAA,MAClG,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,eAAe,MAAM;AAE1B,YAAM,iBAAiB;AACvB,UAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,eAAO,iCAAiC,IAAI;AAAA,MAC9C;AACA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,UAAU,MAAM;AACrB,aAAO,KAAK,QAAQ,kBAAkB,+FAA+F;AACrI,aAAO,KAAK,QAAQ,cAAc,+FAA+F;AACjI,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,OAAO,YAAY,MAAM;AAGvB,aAAO,KAAK,QAAQ,WAAC,gDAAuC,GAAC,GAAE,qFAAqF;AAIpJ,aAAO,KAAK,QAAQ,WAAC,8CAAyC,GAAC,GAAE,qFAAqF;AAEtJ,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,OAAO,mBAAmB,MAAM;AAE9B,aAAO,KAAK,QAAQ,WAAC,mCAAgC,GAAC,GAAE,yFAAyF;AAEjJ,aAAO,KAAK,QAAQ,WAAC,iCAA8B,GAAC,GAAE,uFAAuF;AAC7I,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,gBAAgB,MAAM;AAS3B,aAAO,KAAK,QAAQ,WAAC,6CAAwC,GAAC,GAAE,2FAA2F;AAAA,IAC7J;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,YAAY,KAAK;AAEtB,YAAM,UAAU,IAAI,KAAK;AACzB,YAAM,QAAQ,QAAQ,YAAY;AAGlC,YAAM,gBAAgB;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,YAAM,kBAAkB,cAAc,KAAK,cAAY,MAAM,WAAW,QAAQ,CAAC;AAGjF,YAAM,aAAa,QAAQ,WAAW,GAAG,KACvB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACrB,CAAC,QAAQ,SAAS,GAAG,KAAK,CAAC,QAAQ,SAAS,IAAI;AAGnE,UAAI,mBAAmB,YAAY;AACjC,eAAO;AAAA,MACT;AAGA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,WAAW,MAAM;AACtB,aAAO,KAAK,QAAQ,uBAAuB,CAAC,OAAO,MAAM,QAAQ;AAC/D,cAAM,aAAa,UAAU,KAAK,WAAW;AAE7C,cAAM,UAAU,KAAK,YAAY,GAAG;AAEpC,eAAO,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,IAAI,0CAA0C,GAAG;AAAA,MACzJ,CAAC;AAAA,IACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,8BAA8B,MAAM;AACzC,YAAM,cAAc,oBAAI,IAAI;AAC5B,UAAI,mBAAmB;AACvB,UAAI,gBAAgB;AAGpB,YAAM,mBAAmB,CAAC;AAG1B,YAAM,YAAY;AAClB,UAAI;AACJ,cAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAIlD,cAAM,aAAa,UAAU,QAAQ,UAAU,CAAC,EAAE,QAAQ,IAAI;AAC9D,cAAM,WAAW,aAAa;AAC9B,cAAM,SAAS,WAAW,UAAU,CAAC,EAAE;AACvC,yBAAiB,KAAK,EAAE,OAAO,UAAU,KAAK,OAAO,CAAC;AAAA,MACxD;AAGA,YAAM,YAAY,WAAC,6CAAwC,GAAC;AAC5D,UAAI;AACJ,YAAM,cAAc,CAAC;AAErB,cAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAClD,cAAM,YAAY,UAAU;AAC5B,cAAM,UAAU,UAAU,QAAQ,UAAU,CAAC,EAAE;AAG/C,cAAM,oBAAoB,iBAAiB;AAAA,UAAK,YAC9C,aAAa,OAAO,SAAS,WAAW,OAAO;AAAA,QACjD;AAEA,YAAI,CAAC,mBAAmB;AACtB,sBAAY,KAAK;AAAA,YACf,OAAO,UAAU,CAAC;AAAA,YAClB,OAAO,UAAU;AAAA,YACjB,WAAW,UAAU,CAAC;AAAA,YACtB,SAAS,UAAU,CAAC;AAAA,YACpB,YAAY,UAAU,CAAC;AAAA,UACzB,CAAC;AAAA,QACH;AAAA,MACF;AAGA,kBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC5C,kBAAY,QAAQ,cAAY;AAC9B,cAAM,cAAc,SAAS,kBAAkB;AAC/C,oBAAY,IAAI,aAAa;AAAA,UAC3B,MAAM;AAAA,UACN,UAAU,SAAS;AAAA,UACnB,WAAW,SAAS;AAAA,UACpB,SAAS,SAAS;AAAA,UAClB,YAAY,SAAS;AAAA,QACvB,CAAC;AACD,wBAAgB,cAAc,UAAU,GAAG,SAAS,KAAK,IAC1C,cACA,cAAc,UAAU,SAAS,QAAQ,SAAS,MAAM,MAAM;AAAA,MAC/E,CAAC;AAGD,sBAAgB,cAAc,QAAQ,4BAA4B,CAAC,OAAO,UAAU,QAAQ;AAC1F,cAAM,cAAc,SAAS,kBAAkB;AAC/C,oBAAY,IAAI,aAAa;AAAA,UAC3B,MAAM;AAAA,UACN,UAAU;AAAA,UACV;AAAA,UACA;AAAA,QACF,CAAC;AACD,eAAO;AAAA,MACT,CAAC;AAED,aAAO,EAAE,eAAe,YAAY;AAAA,IACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,OAAO,+BAA+B,MAAM,aAAa;AAEvD,YAAM,eAAe,MAAM,KAAK,YAAY,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACjE,cAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,cAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,eAAO,SAAS;AAAA,MAClB,CAAC;AAED,mBAAa,QAAQ,iBAAe;AAClC,cAAM,YAAY,YAAY,IAAI,WAAW;AAC7C,YAAI;AAEJ,YAAI,UAAU,SAAS,QAAQ;AAE7B,wBAAc,qCAAqC,UAAU,SAAS,UAAU,UAAU,OAAO,+BAA+B,UAAU,UAAU;AAAA,QACtJ,WAAW,UAAU,SAAS,QAAQ;AAEpC,cAAI,oBAAoB,UAAU;AAIlC,sBAAY,QAAQ,CAAC,gBAAgB,qBAAqB;AACxD,gBAAI,kBAAkB,SAAS,gBAAgB,GAAG;AAChD,kBAAI,eAAe,SAAS,QAAQ;AAClC,sBAAM,WAAW,qCAAqC,eAAe,SAAS,UAAU,eAAe,OAAO,+BAA+B,eAAe,UAAU;AACtK,oCAAoB,kBAAkB,QAAQ,kBAAkB,QAAQ;AAAA,cAC1E;AAAA,YACF;AAAA,UACF,CAAC;AAGD,8BAAoB,KAAK,mBAAmB,iBAAiB;AAC7D,8BAAoB,KAAK,UAAU,iBAAiB;AACpD,8BAAoB,KAAK,YAAY,iBAAiB;AAItD,gBAAM,aAAa,UAAU,KAAK,WAAW;AAC7C,gBAAM,UAAU,KAAK,YAAY,UAAU,GAAG;AAC9C,wBAAc,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,iBAAiB,0CAA0C,UAAU,GAAG;AAAA,QACvL;AAEA,eAAO,KAAK,QAAQ,aAAa,WAAW;AAAA,MAC9C,CAAC;AAED,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,oBAAoB,MAAM;AAE/B,YAAM,EAAE,eAAe,YAAY,IAAI,KAAK,8BAA8B,IAAI;AAG9E,UAAI,OAAO;AACX,aAAO,KAAK,mBAAmB,IAAI;AACnC,aAAO,KAAK,UAAU,IAAI;AAC1B,aAAO,KAAK,YAAY,IAAI;AAG5B,aAAO,KAAK,+BAA+B,MAAM,WAAW;AAE5D,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,UAAU,MAAM,gBAAgB,OAAO;AAC5C,UAAI,OAAO,KAAK,WAAW,IAAI;AAG/B,aAAO,KAAK,oBAAoB,MAAM,IAAI;AAG1C,YAAM,iBAAiB,KAAK,oBAAoB,IAAI;AACpD,UAAI;AAAgB,eAAO;AAE3B,YAAM,YAAY,KAAK,eAAe,IAAI;AAC1C,UAAI;AAAW,eAAO;AAGtB,aAAO,KAAK,YAAY,IAAI;AAC5B,aAAO,KAAK,gBAAgB,IAAI;AAChC,aAAO,KAAK,cAAc,MAAM,aAAa;AAC7C,aAAO,KAAK,gBAAgB,IAAI;AAChC,aAAO,KAAK,kBAAkB,IAAI;AAGlC,aAAO,KAAK,oBAAoB,IAAI;AAGpC,UAAI,KAAK,KAAK,MAAM,IAAI;AAGtB,eAAO;AAAA,MACT;AAEA,aAAO,QAAQ,IAAI;AAAA,IACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUA,OAAO,MAAM,MAAM,aAAa,IAAI,oBAAoB,OAAO,qBAAqB,gBAAgB,OAAO;AAEzG,WAAK,eAAe;AAEpB,YAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAI,cAAc;AAElB,YAAM,cAAc,MAAM,IAAI,CAAC,MAAM,UAAU;AAE7C,YAAI,qBAAqB,UAAU,YAAY;AAC7C,gBAAM,UAAU,KAAK,WAAW,IAAI,KAAK;AACzC,iBAAO,yBAAyB,OAAO;AAAA,QACzC;AAGA,cAAM,iBAAiB;AACvB,YAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,wBAAc,CAAC;AAEf,iBAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,QACnE;AAGA,YAAI,aAAa;AACf,gBAAM,UAAU,KAAK,WAAW,IAAI;AACpC,gBAAM,WAAW,KAAK,oBAAoB,SAAS,IAAI;AACvD,iBAAO,QAAQ,YAAY,QAAQ;AAAA,QACrC;AAGA,eAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,MACnE,CAAC;AAGD,YAAM,OAAO,YAAY,KAAK,EAAE;AAGhC,aAAO,KAAK,gBAAgB,MAAM,mBAAmB;AAAA,IACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,OAAO,gBAAgB,MAAM,qBAAqB;AAEhD,UAAI,OAAO,aAAa,eAAe,CAAC,UAAU;AAEhD,eAAO,KAAK,sBAAsB,MAAM,mBAAmB;AAAA,MAC7D;AAGA,YAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,gBAAU,YAAY;AAEtB,UAAI,cAAc;AAClB,UAAI,WAAW;AACf,UAAI,mBAAmB;AACvB,UAAI,cAAc;AAGlB,YAAM,WAAW,MAAM,KAAK,UAAU,QAAQ;AAE9C,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,cAAM,QAAQ,SAAS,CAAC;AAGxB,YAAI,CAAC,MAAM;AAAY;AAGvB,cAAM,YAAY,MAAM,cAAc,aAAa;AACnD,YAAI,WAAW;AACb,gBAAM,YAAY,UAAU;AAC5B,cAAI,UAAU,WAAW,KAAK,GAAG;AAC/B,gBAAI,CAAC,aAAa;AAEhB,4BAAc;AAGd,iCAAmB,SAAS,cAAc,KAAK;AAC/C,oBAAM,cAAc,SAAS,cAAc,MAAM;AACjD,+BAAiB,YAAY,WAAW;AACxC,+BAAiB,YAAY;AAG7B,oBAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,kBAAI,MAAM;AACR,4BAAY,YAAY,YAAY,IAAI;AAAA,cAC1C;AAGA,wBAAU,aAAa,kBAAkB,MAAM,WAAW;AAG1D,+BAAiB,eAAe;AAChC,+BAAiB,YAAY;AAC7B,+BAAiB,eAAe;AAChC;AAAA,YACF,OAAO;AAGL,oBAAM,cAAc,uBAAuB,KAAK;AAChD,kBAAI,oBAAoB,eAAe,iBAAiB,cAAc;AACpE,oBAAI;AACF,wBAAM,SAAS;AAAA,oBACb,iBAAiB;AAAA,oBACjB,iBAAiB,aAAa;AAAA,kBAChC;AAGA,sBAAI,UAAU,OAAO,OAAO,SAAS,YAAY;AAC/C,4BAAQ,KAAK,kOAAkO;AAAA,kBAEjP,OAAO;AAGL,wBAAI,UAAU,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AACzD,uCAAiB,aAAa,YAAY;AAAA,oBAC5C;AAAA,kBAEF;AAAA,gBACF,SAAS,OAAO;AACd,0BAAQ,KAAK,6BAA6B,KAAK;AAAA,gBAEjD;AAAA,cACF;AAEA,4BAAc;AACd,iCAAmB;AACnB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAGA,YAAI,eAAe,oBAAoB,MAAM,YAAY,SAAS,CAAC,MAAM,cAAc,aAAa,GAAG;AACrG,gBAAM,cAAc,iBAAiB,gBAAgB,iBAAiB,cAAc,MAAM;AAE1F,cAAI,iBAAiB,aAAa,SAAS,GAAG;AAC5C,6BAAiB,gBAAgB;AAAA,UACnC;AAEA,gBAAM,WAAW,MAAM,YAAY,QAAQ,WAAW,GAAG;AACzD,2BAAiB,gBAAgB;AAGjC,cAAI,YAAY,YAAY,SAAS,GAAG;AACtC,wBAAY,eAAe;AAAA,UAC7B;AACA,sBAAY,eAAe;AAC3B,gBAAM,OAAO;AACb;AAAA,QACF;AAGA,YAAI,WAAW;AACf,YAAI,MAAM,YAAY,OAAO;AAE3B,qBAAW,MAAM,cAAc,IAAI;AAAA,QACrC;AAEA,YAAI,UAAU;AACZ,gBAAM,WAAW,SAAS,UAAU,SAAS,aAAa;AAC1D,gBAAM,YAAY,SAAS,UAAU,SAAS,cAAc;AAE5D,cAAI,CAAC,YAAY,CAAC,WAAW;AAC3B,0BAAc;AACd,uBAAW;AACX;AAAA,UACF;AAEA,gBAAM,UAAU,WAAW,OAAO;AAGlC,cAAI,CAAC,eAAe,aAAa,SAAS;AACxC,0BAAc,SAAS,cAAc,OAAO;AAC5C,sBAAU,aAAa,aAAa,KAAK;AACzC,uBAAW;AAAA,UACb;AAGA,gBAAM,mBAAmB,CAAC;AAC1B,qBAAW,QAAQ,MAAM,YAAY;AACnC,gBAAI,KAAK,aAAa,KAAK,KAAK,YAAY,MAAM,WAAW,GAAG;AAE9D,+BAAiB,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,YAC5C,WAAW,SAAS,UAAU;AAC5B;AAAA,YACF;AAAA,UACF;AAGA,2BAAiB,QAAQ,UAAQ;AAC/B,qBAAS,aAAa,MAAM,SAAS,UAAU;AAAA,UACjD,CAAC;AAGD,sBAAY,YAAY,QAAQ;AAGhC,gBAAM,OAAO;AAAA,QACf,OAAO;AAEL,wBAAc;AACd,qBAAW;AAAA,QACb;AAAA,MACF;AAEA,aAAO,UAAU;AAAA,IACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,OAAO,sBAAsB,MAAM,qBAAqB;AACtD,UAAI,YAAY;AAGhB,kBAAY,UAAU,QAAQ,wEAAwE,CAAC,UAAU;AAC/G,cAAM,OAAO,MAAM,MAAM,4DAA4D,KAAK,CAAC;AAC3F,YAAI,KAAK,SAAS,GAAG;AACnB,gBAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,kBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,kBAAM,gBAAgB,IAAI,MAAM,mCAAmC;AAEnE,gBAAI,eAAe,eAAe;AAChC,oBAAM,cAAc,YAAY,CAAC;AACjC,oBAAM,WAAW,cAAc,CAAC;AAEhC,qBAAO,SAAS,QAAQ,4BAA4B,2BAA2B,WAAW,EAAE;AAAA,YAC9F;AACA,mBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,UAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,iBAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,QACnC;AACA,eAAO;AAAA,MACT,CAAC;AAGD,kBAAY,UAAU,QAAQ,yEAAyE,CAAC,UAAU;AAChH,cAAM,OAAO,MAAM,MAAM,6DAA6D,KAAK,CAAC;AAC5F,YAAI,KAAK,SAAS,GAAG;AACnB,gBAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,kBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,kBAAM,gBAAgB,IAAI,MAAM,oCAAoC;AAEpE,gBAAI,eAAe,eAAe;AAChC,oBAAM,cAAc,YAAY,CAAC;AACjC,oBAAM,WAAW,cAAc,CAAC;AAEhC,qBAAO,SAAS,QAAQ,6BAA6B,4BAA4B,WAAW,EAAE;AAAA,YAChG;AACA,mBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,UAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,iBAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,QACnC;AACA,eAAO;AAAA,MACT,CAAC;AAGD,YAAM,iBAAiB;AACvB,kBAAY,UAAU,QAAQ,gBAAgB,CAAC,OAAO,WAAW,SAAS,eAAe;AAEvF,cAAM,QAAQ,QAAQ,MAAM,qBAAqB,KAAK,CAAC;AACvD,cAAM,cAAc,MAAM,IAAI,UAAQ;AAEpC,gBAAM,OAAO,KAAK,QAAQ,sBAAsB,IAAI,EACjD,QAAQ,WAAW,GAAG;AACzB,iBAAO;AAAA,QACT,CAAC,EAAE,KAAK,IAAI;AAGZ,cAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,cAAM,YAAY,OAAO,oBAAoB,IAAI,MAAM;AAGvD,YAAI,qBAAqB;AAEzB,cAAM,cAAc,uBAAuB,KAAK;AAChD,YAAI,aAAa;AACf,cAAI;AAIF,kBAAM,cAAc,YACjB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,UAAU,GAAG;AAExB,kBAAMA,UAAS,YAAY,aAAa,IAAI;AAI5C,gBAAIA,WAAU,OAAOA,QAAO,SAAS,YAAY;AAC/C,sBAAQ,KAAK,4HAA4H;AAAA,YAE3I,OAAO;AAEL,kBAAIA,WAAU,OAAOA,YAAW,YAAYA,QAAO,KAAK,GAAG;AACzD,qCAAqBA;AAAA,cACvB;AAAA,YAEF;AAAA,UACF,SAAS,OAAO;AACd,oBAAQ,KAAK,6BAA6B,KAAK;AAAA,UAEjD;AAAA,QACF;AAGA,YAAI,SAAS,iCAAiC,SAAS;AAEvD,kBAAU,gCAAgC,SAAS,IAAI,kBAAkB;AACzE,kBAAU,iCAAiC,UAAU;AAErD,eAAO;AAAA,MACT,CAAC;AAED,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiBA,OAAO,eAAe,MAAM,gBAAgB;AAE1C,YAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAI,aAAa;AACjB,UAAI,YAAY;AAChB,UAAI,YAAY;AAEhB,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAM,aAAa,MAAM,CAAC,EAAE;AAC5B,YAAI,aAAa,cAAc,gBAAgB;AAC7C,sBAAY;AACZ,sBAAY;AACZ;AAAA,QACF;AACA,sBAAc,aAAa;AAAA,MAC7B;AAEA,YAAM,cAAc,MAAM,SAAS;AACnC,YAAM,UAAU,YAAY,YAAY;AAGxC,YAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,UAAI,eAAe;AACjB,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,QAAQ,cAAc,CAAC;AAAA,UACvB,QAAQ;AAAA,UACR,SAAS,cAAc,CAAC,MAAM;AAAA,UAC9B,SAAS,cAAc,CAAC;AAAA,UACxB;AAAA,UACA;AAAA,UACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,QAChF;AAAA,MACF;AAGA,YAAM,cAAc,YAAY,MAAM,KAAK,cAAc,MAAM;AAC/D,UAAI,aAAa;AACf,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,QAAQ,YAAY,CAAC;AAAA,UACrB,QAAQ,YAAY,CAAC;AAAA,UACrB,SAAS,YAAY,CAAC;AAAA,UACtB;AAAA,UACA;AAAA,UACA,cAAc,YAAY,YAAY,CAAC,EAAE,SAAS,YAAY,CAAC,EAAE,SAAS;AAAA;AAAA,QAC5E;AAAA,MACF;AAGA,YAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,UAAI,eAAe;AACjB,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,QAAQ,cAAc,CAAC;AAAA,UACvB,QAAQ,SAAS,cAAc,CAAC,CAAC;AAAA,UACjC,SAAS,cAAc,CAAC;AAAA,UACxB;AAAA,UACA;AAAA,UACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,QAChF;AAAA,MACF;AAGA,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,cAAc;AAAA,MAChB;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,kBAAkB,SAAS;AAChC,cAAQ,QAAQ,UAAU;AAAA,QACxB,KAAK;AACH,iBAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,MAAM;AAAA,QAC3C,KAAK;AACH,iBAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,SAAS,CAAC;AAAA,QAC/C,KAAK;AACH,iBAAO,GAAG,QAAQ,MAAM;AAAA,QAC1B;AACE,iBAAO;AAAA,MACX;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,OAAO,cAAc,MAAM;AACzB,YAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,YAAM,kBAAkB,oBAAI,IAAI;AAChC,UAAI,SAAS;AAEb,YAAM,SAAS,MAAM,IAAI,UAAQ;AAC/B,cAAM,QAAQ,KAAK,MAAM,KAAK,cAAc,QAAQ;AAEpD,YAAI,OAAO;AACT,gBAAM,SAAS,MAAM,CAAC;AACtB,gBAAM,cAAc,OAAO;AAC3B,gBAAM,UAAU,MAAM,CAAC;AAGvB,cAAI,CAAC,QAAQ;AACX,4BAAgB,MAAM;AAAA,UACxB;AAGA,gBAAM,iBAAiB,gBAAgB,IAAI,WAAW,KAAK,KAAK;AAChE,0BAAgB,IAAI,aAAa,aAAa;AAG9C,qBAAW,CAAC,KAAK,KAAK,iBAAiB;AACrC,gBAAI,QAAQ,aAAa;AACvB,8BAAgB,OAAO,KAAK;AAAA,YAC9B;AAAA,UACF;AAEA,mBAAS;AACT,iBAAO,GAAG,MAAM,GAAG,aAAa,KAAK,OAAO;AAAA,QAC9C,OAAO;AAEL,cAAI,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,MAAM,KAAK,GAAG;AAE5C,qBAAS;AACT,4BAAgB,MAAM;AAAA,UACxB;AACA,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AAED,aAAO,OAAO,KAAK,IAAI;AAAA,IACzB;AAAA,EACF;AA18BE;AAAA,gBAFW,gBAEJ,aAAY;AAGnB;AAAA,gBALW,gBAKJ,mBAAkB;AAGzB;AAAA,gBARW,gBAQJ,gBAAe;AAsyBtB;AAAA;AAAA;AAAA,gBA9yBW,gBA8yBJ,iBAAgB;AAAA,IACrB,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;;;AClzBK,MAAM,mBAAN,MAAuB;AAAA,IAC5B,YAAY,QAAQ;AAClB,WAAK,SAAS;AAAA,IAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,cAAc,OAAO;AACnB,YAAM,QAAQ,UAAU,SAAS,YAAY,EAAE,SAAS,KAAK;AAC7D,YAAM,SAAS,QAAQ,MAAM,UAAU,MAAM;AAE7C,UAAI,CAAC;AAAQ,eAAO;AAEpB,UAAI,WAAW;AAEf,cAAQ,MAAM,IAAI,YAAY,GAAG;AAAA,QAC/B,KAAK;AACH,cAAI,CAAC,MAAM;AAAU,uBAAW;AAChC;AAAA,QACF,KAAK;AACH,cAAI,CAAC,MAAM;AAAU,uBAAW;AAChC;AAAA,QACF,KAAK;AACH,cAAI,CAAC,MAAM;AAAU,uBAAW;AAChC;AAAA,QACF,KAAK;AACH,cAAI,MAAM;AAAU,uBAAW;AAC/B;AAAA,QACF,KAAK;AACH,cAAI,MAAM;AAAU,uBAAW;AAC/B;AAAA,MACJ;AAEA,UAAI,UAAU;AACZ,cAAM,eAAe;AACrB,aAAK,OAAO,cAAc,UAAU,KAAK;AACzC,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA,IAKA,UAAU;AAAA,IAEV;AAAA,EACF;;;ACnDO,MAAM,QAAQ;AAAA,IACnB,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,WAAW;AAAA;AAAA,MACX,aAAa;AAAA;AAAA,MACb,MAAM;AAAA;AAAA,MACN,aAAa;AAAA;AAAA,MACb,eAAe;AAAA;AAAA,MACf,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,QAAQ;AAAA;AAAA,MACR,IAAI;AAAA;AAAA,MACJ,KAAK;AAAA;AAAA,MACL,MAAM;AAAA;AAAA,MACN,MAAM;AAAA;AAAA,MACN,QAAQ;AAAA;AAAA,MACR,YAAY;AAAA;AAAA,MACZ,IAAI;AAAA;AAAA,MACJ,cAAc;AAAA;AAAA,MACd,QAAQ;AAAA;AAAA,MACR,QAAQ;AAAA;AAAA,MACR,WAAW;AAAA;AAAA,MACX,YAAY;AAAA;AAAA,MACZ,SAAS;AAAA;AAAA,MACT,QAAQ;AAAA;AAAA,MACR,SAAS;AAAA;AAAA,MACT,SAAS;AAAA;AAAA;AAAA,MAET,WAAW;AAAA;AAAA,MACX,aAAa;AAAA;AAAA,MACb,cAAc;AAAA;AAAA,MACd,eAAe;AAAA;AAAA,IACjB;AAAA,EACF;AAKO,MAAM,OAAO;AAAA,IAClB,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,WAAW;AAAA;AAAA,MACX,aAAa;AAAA;AAAA,MACb,MAAM;AAAA;AAAA,MACN,aAAa;AAAA;AAAA,MACb,eAAe;AAAA;AAAA,MACf,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,QAAQ;AAAA;AAAA,MACR,IAAI;AAAA;AAAA,MACJ,KAAK;AAAA;AAAA,MACL,MAAM;AAAA;AAAA,MACN,MAAM;AAAA;AAAA,MACN,QAAQ;AAAA;AAAA,MACR,YAAY;AAAA;AAAA,MACZ,IAAI;AAAA;AAAA,MACJ,cAAc;AAAA;AAAA,MACd,QAAQ;AAAA;AAAA,MACR,QAAQ;AAAA;AAAA,MACR,WAAW;AAAA;AAAA,MACX,YAAY;AAAA;AAAA,MACZ,SAAS;AAAA;AAAA,MACT,QAAQ;AAAA;AAAA,MACR,SAAS;AAAA;AAAA,MACT,SAAS;AAAA;AAAA;AAAA,MAET,WAAW;AAAA;AAAA,MACX,aAAa;AAAA;AAAA,MACb,cAAc;AAAA;AAAA,MACd,eAAe;AAAA;AAAA,IACjB;AAAA,EACF;AAMO,MAAM,OAAO;AAAA,IAClB,MAAM;AAAA;AAAA,IAEN,QAAQ,MAAM;AAAA;AAAA,EAChB;AAKO,MAAM,SAAS;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAOO,WAAS,SAAS,OAAO;AAC9B,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AAEzC,aAAO,EAAE,GAAG,UAAU,MAAM,MAAM;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AAGA,MAAI,MAAM;AAOH,WAAS,iBAAiB,WAAW;AAC1C,QAAI,cAAc;AAAQ,aAAO;AAGjC,QAAI,CAAC,OAAO,OAAO,YAAY;AAC7B,YAAM,OAAO,WAAW,8BAA8B;AAAA,IACxD;AAEA,YAAO,2BAAK,WAAU,SAAS;AAAA,EACjC;AAgBO,WAAS,eAAe,QAAQ;AACrC,UAAM,OAAO,CAAC;AACd,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAEjD,YAAM,UAAU,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC3D,WAAK,KAAK,KAAK,OAAO,KAAK,KAAK,GAAG;AAAA,IACrC;AACA,WAAO,KAAK,KAAK,IAAI;AAAA,EACvB;AAQO,WAAS,WAAW,WAAW,eAAe,CAAC,GAAG;AACvD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ;AAAA,QACN,GAAG,UAAU;AAAA,QACb,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;;;ACpKO,WAAS,eAAe,UAAU,CAAC,GAAG;AAC3C,UAAM;AAAA,MACJ,WAAW;AAAA,MACX,aAAa;AAAA;AAAA,MAEb,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,CAAC;AAAA,IACZ,IAAI;AAGJ,UAAM,eAAe,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI;AAAA;AAAA;AAAA;AAAA,UAI9C,OAAO,QAAQ,MAAM,EACpB,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AACpB,YAAM,UAAU,KAAK,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC5D,aAAO,GAAG,OAAO,KAAK,GAAG;AAAA,IAC3B,CAAC,EACA,KAAK,YAAY,CAAC;AAAA;AAAA;AAAA,MAGvB;AAGJ,UAAM,YAAY,SAAS,MAAM,SAAS,eAAe,MAAM,MAAM,IAAI;AAEzE,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAyCD,YAAY;AAAA;AAAA,QAEZ,SAAS,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAyCH,UAAU;AAAA;AAAA,6CAEc,QAAQ;AAAA,iDACJ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCASlB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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", + "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n // Single query for containers and wrappers\n const containers = document.querySelectorAll('.overtype-container');\n const wrappers = document.querySelectorAll('.overtype-wrapper');\n \n containers.forEach(el => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n });\n \n wrappers.forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n if (isAuto) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n } else {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n wrapper._instance?.updatePreview();\n });\n \n // Update web components\n document.querySelectorAll('overtype-editor').forEach(wc => {\n if (isAuto) {\n wc.setAttribute?.('theme', 'auto');\n wc.setAttribute?.('data-resolved-theme', themeName);\n } else {\n wc.setAttribute?.('theme', themeName);\n }\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], + "mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons"] } diff --git a/dist/overtype.min.js b/dist/overtype.min.js index 01cc017..048a5d8 100644 --- a/dist/overtype.min.js +++ b/dist/overtype.min.js @@ -5,14 +5,14 @@ * @author David Miranda * https://github.com/panphora/overtype */ -var OverType=(()=>{var F=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var Fe=Object.getOwnPropertyNames;var qe=Object.prototype.hasOwnProperty;var Re=(o,e,t)=>e in o?F(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Ve=(o,e)=>{for(var t in e)F(o,t,{get:e[t],enumerable:!0})},Ue=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Fe(e))!qe.call(o,i)&&i!==t&&F(o,i,{get:()=>e[i],enumerable:!(n=Oe(e,i))||n.enumerable});return o};var De=o=>Ue(F({},"__esModule",{value:!0}),o);var E=(o,e,t)=>(Re(o,typeof e!="symbol"?e+"":e,t),t);var at={};Ve(at,{OverType:()=>I,default:()=>st,defaultToolbarButtons:()=>N,toolbarButtons:()=>k});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,n=>t[n])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,n,i)=>{let r=n.length;return`${n} ${i}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,n)=>`> ${n}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(n,i,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${i}
  • ${s}
  • `}else return`${i}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),n=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>n.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,n,i)=>{let r=`--link-${this.linkIndex++}`;return`
    [${n}](${i})`})}static identifyAndProtectSanctuaries(e){let t=new Map,n=0,i=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,m=h+a[2].length;r.push({start:h,end:m})}let c=new RegExp("(?p>=g.start&&h<=g.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((p,h)=>h.index-p.index),l.forEach(p=>{let h=`\uE000${n++}\uE001`;t.set(h,{type:"code",original:p.match,openTicks:p.openTicks,content:p.content,closeTicks:p.closeTicks}),i=i.substring(0,p.index)+h+i.substring(p.index+p.match.length)}),i=i.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(p,h,m)=>{let g=`\uE000${n++}\uE001`;return t.set(g,{type:"link",original:p,linkText:h,url:m}),g}),{protectedText:i,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((i,r)=>{let s=e.indexOf(i),a=e.indexOf(r);return s-a}).forEach(i=>{let r=t.get(i),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,p)=>{if(a.includes(p)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(p,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let c=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(i,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:n}=this.identifyAndProtectSanctuaries(e),i=t;return i=this.parseStrikethrough(i),i=this.parseBold(i),i=this.parseItalic(i),i=this.restoreAndTransformSanctuaries(i,n),i}static parseLine(e,t=!1){let n=this.escapeHtml(e);n=this.preserveIndentation(n,e);let i=this.parseHorizontalRule(n);if(i)return i;let r=this.parseCodeBlock(n);return r||(n=this.parseHeader(n),n=this.parseBlockquote(n),n=this.parseTaskList(n,t),n=this.parseBulletList(n),n=this.parseNumberedList(n),n=this.parseInlineElements(n),n.trim()===""?"
     
    ":`
    ${n}
    `)}static parse(e,t=-1,n=!1,i,r=!1){this.resetLinkIndex();let s=e.split(` +var OverType=(()=>{var O=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var qe=(o,e,t)=>e in o?O(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Ve=(o,e)=>{for(var t in e)O(o,t,{get:e[t],enumerable:!0})},Ue=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!Re.call(o,i)&&i!==t&&O(o,i,{get:()=>e[i],enumerable:!(n=Fe(e,i))||n.enumerable});return o};var De=o=>Ue(O({},"__esModule",{value:!0}),o);var E=(o,e,t)=>(qe(o,typeof e!="symbol"?e+"":e,t),t);var at={};Ve(at,{OverType:()=>I,default:()=>st,defaultToolbarButtons:()=>N,toolbarButtons:()=>k});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,n=>t[n])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,n,i)=>{let r=n.length;return`${n} ${i}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,n)=>`> ${n}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(n,i,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${i}
  • ${s}
  • `}else return`${i}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),n=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>n.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,n,i)=>{let r=`--link-${this.linkIndex++}`;return`[${n}](${i})`})}static identifyAndProtectSanctuaries(e){let t=new Map,n=0,i=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,m=h+a[2].length;r.push({start:h,end:m})}let c=new RegExp("(?p>=g.start&&h<=g.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((p,h)=>h.index-p.index),l.forEach(p=>{let h=`\uE000${n++}\uE001`;t.set(h,{type:"code",original:p.match,openTicks:p.openTicks,content:p.content,closeTicks:p.closeTicks}),i=i.substring(0,p.index)+h+i.substring(p.index+p.match.length)}),i=i.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(p,h,m)=>{let g=`\uE000${n++}\uE001`;return t.set(g,{type:"link",original:p,linkText:h,url:m}),g}),{protectedText:i,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((i,r)=>{let s=e.indexOf(i),a=e.indexOf(r);return s-a}).forEach(i=>{let r=t.get(i),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,p)=>{if(a.includes(p)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(p,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let c=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(i,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:n}=this.identifyAndProtectSanctuaries(e),i=t;return i=this.parseStrikethrough(i),i=this.parseBold(i),i=this.parseItalic(i),i=this.restoreAndTransformSanctuaries(i,n),i}static parseLine(e,t=!1){let n=this.escapeHtml(e);n=this.preserveIndentation(n,e);let i=this.parseHorizontalRule(n);if(i)return i;let r=this.parseCodeBlock(n);return r||(n=this.parseHeader(n),n=this.parseBlockquote(n),n=this.parseTaskList(n,t),n=this.parseBulletList(n),n=this.parseNumberedList(n),n=this.parseInlineElements(n),n.trim()===""?"
     
    ":`
    ${n}
    `)}static parse(e,t=-1,n=!1,i,r=!1){this.resetLinkIndex();let s=e.split(` `),a=!1,d=s.map((l,p)=>{if(n&&p===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let m=this.escapeHtml(l);return`
    ${this.preserveIndentation(m,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,i)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let n=document.createElement("div");n.innerHTML=e;let i=null,r=null,s=null,a=!1,c=Array.from(n.children);for(let d=0;d0&&(s._codeContent+=` `);let g=l.textContent.replace(/\u00A0/g," ");s._codeContent+=g,m.textContent.length>0&&(m.textContent+=` `),m.textContent+=g,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let m=h.classList.contains("bullet-list"),g=h.classList.contains("ordered-list");if(!m&&!g){i=null,r=null;continue}let f=m?"ul":"ol";(!i||r!==f)&&(i=document.createElement(f),n.insertBefore(i,l),r=f);let v=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))v.push(y.cloneNode(!0));else if(y===h)break;v.forEach(y=>{h.insertBefore(y,h.firstChild)}),i.appendChild(h),l.remove()}else i=null,r=null}return n.innerHTML}static postProcessHTMLManual(e,t){let n=e;n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    • /,`
    • ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    2. /,`
    3. ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let i=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return n=n.replace(i,(r,s,a,c)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(v=>v.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` `),p=s.slice(3).trim(),h=p?` class="language-${p}"`:"",m=l,g=t||this.codeHighlighter;if(g)try{let v=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=g(v,p);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(m=y)}catch(v){console.warn("Code highlighting failed:",v)}let f=`
    ${s}
    `;return f+=`
    ${m}
    `,f+=`
    ${c}
    `,f}),n}static getListContext(e,t){let n=e.split(` `),i=0,r=0,s=0;for(let h=0;h=t){r=h,s=i;break}i+=m+1}let a=n[r],c=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:c,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:c,markerEndPos:s+l[1].length+l[2].length+1};let p=a.match(this.LIST_PATTERNS.numbered);return p?{inList:!0,listType:"numbered",indent:p[1],marker:parseInt(p[2]),content:p[3],lineStart:s,lineEnd:c,markerEndPos:s+p[1].length+p[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:c,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` `),n=new Map,i=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let c=a[1],d=c.length,l=a[3];i||n.clear();let p=(n.get(d)||0)+1;n.set(d,p);for(let[h]of n)h>d&&n.delete(h);return i=!0,`${c}${p}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(i=!1,n.clear()),s}).join(` -`)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var j=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.performAction(i,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ee={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},We={name:"auto",colors:A.colors},te={solar:A,cave:ee,auto:We,light:A,dark:ee};function M(o){return typeof o=="string"?{...te[o]||te.solar,name:o}:o}var z=null;function K(o){return o!=="auto"?o:(!z&&window.matchMedia&&(z=window.matchMedia("(prefers-color-scheme: dark)")),z!=null&&z.matches?"cave":"solar")}function _(o){let e=[];for(let[t,n]of Object.entries(o)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${n};`)}return e.join(` +`)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.performAction(i,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ee={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},We={name:"auto",colors:A.colors},te={solar:A,cave:ee,auto:We,light:A,dark:ee};function M(o){return typeof o=="string"?{...te[o]||te.solar,name:o}:o}var j=null;function K(o){return o!=="auto"?o:(!j&&window.matchMedia&&(j=window.matchMedia("(prefers-color-scheme: dark)")),j!=null&&j.matches?"cave":"solar")}function _(o){let e=[];for(let[t,n]of Object.entries(o)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${n};`)}return e.join(` `)}function G(o,e={}){return{...o,colors:{...o.colors,...e}}}function ne(o={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:n='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:s={}}=o,a=Object.keys(s).length>0?` @media (max-width: 640px) { .overtype-wrapper .overtype-input, @@ -861,7 +861,7 @@ var OverType=(()=>{var F=Object.defineProperty;var Oe=Object.getOwnPropertyDescr } ${a} - `}var Ke=Object.defineProperty,oe=Object.getOwnPropertySymbols,Ge=Object.prototype.hasOwnProperty,Ze=Object.prototype.propertyIsEnumerable,ie=(o,e,t)=>e in o?Ke(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,re=(o,e)=>{for(var t in e||(e={}))Ge.call(e,t)&&ie(o,t,e[t]);if(oe)for(var t of oe(e))Ze.call(e,t)&&ie(o,t,e[t]);return o},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Je(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return re(re({},Je()),o)}var R=!1;function Qe(){return R}function b(o,e,t){R&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function q(o,e){if(!R)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function ce(o){R&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function P(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Qe();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),c=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` + `}var Ke=Object.defineProperty,oe=Object.getOwnPropertySymbols,Ge=Object.prototype.hasOwnProperty,Ze=Object.prototype.propertyIsEnumerable,ie=(o,e,t)=>e in o?Ke(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,re=(o,e)=>{for(var t in e||(e={}))Ge.call(e,t)&&ie(o,t,e[t]);if(oe)for(var t of oe(e))Ze.call(e,t)&&ie(o,t,e[t]);return o},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Je(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return re(re({},Je()),o)}var q=!1;function Qe(){return q}function b(o,e,t){q&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function R(o,e){if(!q)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function ce(o){q&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function P(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Qe();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),c=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` `).length,"lines")}catch(p){H=!1,i&&console.log("execCommand threw error:",p)}o.contentEditable="false"}if(i&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let p=a+e+c,h=o.value;i&&(console.log("Expected length:",p.length),console.log("Actual length:",h.length)),h!==p&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(p.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!H)if(i&&console.log("Using manual insertion"),o.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(p){}o.value=a+e+c;try{document.execCommand("ms-endUndoUnit")}catch(p){}o.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,n),t!=null&&n!=null?o.setSelectionRange(t,n):o.setSelectionRange(r,o.selectionEnd),i&&(console.log("Final value length:",o.value.length),console.groupEnd())}function se(o){return o.trim().split(` `).length>1}function Xe(o,e){let t=e;for(;o[t]&&o[t-1]!=null&&!o[t-1].match(/\s/);)t--;return t}function Ye(o,e,t){let n=e,i=t?/\n/:/\s/;for(;o[n]&&!o[n].match(i);)n++;return n}function pe(o){let e=o.value.split(` `),t=0;for(let n=0;n=t&&o.selectionStart=t&&o.selectionEndt.test(r)),i=e;return n&&(i=e.map(r=>r.replace(t,""))),{text:i.join(` `),processed:n}}function le(o){let e=o.split(` `),t="- ",n=e.every(r=>r.startsWith(t)),i=e;return n&&(i=e.map(r=>r.slice(t.length))),{text:i.join(` -`),processed:n}}function O(o,e){return e?"- ":`${o+1}. `}function tt(o,e){let t,n,i;return o.orderedList?(t=ae(e),n=le(t.text),i=n.text):(t=le(e),n=ae(t.text),i=n.text),[t,n,i]}function nt(o,e){let t=o.selectionStart===o.selectionEnd,n=o.selectionStart,i=o.selectionEnd;pe(o);let r=o.value.slice(o.selectionStart,o.selectionEnd),[s,a,c]=tt(e,r),d=c.split(` -`).map((f,v)=>`${O(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+O(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+O(y,!e.unorderedList).length,0);if(s.processed)return t?(n=Math.max(n-O(0,e.unorderedList).length,0),i=n):(n=o.selectionStart,i=o.selectionEnd-l),{text:c,selectionStart:n,selectionEnd:i};let{newlinesToAppend:h,newlinesToPrepend:m}=Z(o),g=h+d.join(` -`)+m;return t?(n=Math.max(n+O(0,e.unorderedList).length+h.length,0),i=n):a.processed?(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l-p):(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l),{text:g,selectionStart:n,selectionEnd:i}}function ue(o,e){let t=V(o,n=>nt(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),h=e.orderedList&&l||e.unorderedList&&p;if(i===r)if(h){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(i-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:i+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:i+m}}else if(h){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(r-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:r+m}}}});P(o,t)}function ot(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` -`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(c,d);if(l.includes("**")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("**"),g=h.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("_"),g=h.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100));p.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("["),g=h.indexOf("]");m!==-1&&g!==-1&&i.slice(n+g+1,n+g+10).startsWith("(")&&e.push("link")}return e}function he(o){if(!o||o.disabled||o.readOnly)return;b("toggleBold","Starting"),q(o,"Before");let e=$(T.bold),t=U(o,e);ce(t),P(o,t),q(o,"After")}function me(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.italic),t=U(o,e);P(o,t)}function fe(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.code),t=U(o,e);P(o,t)}function ge(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=$(T.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);P(o,r)}function ve(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.bulletList);ue(o,e)}function ye(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.numberedList);ue(o,e)}function be(o){if(!o||o.disabled||o.readOnly)return;b("toggleQuote","Starting"),q(o,"Initial");let e=$(T.quote),t=V(o,n=>de(n,e),{prefix:e.prefix});ce(t),P(o,t),q(o,"Final")}function J(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.taskList),t=V(o,n=>de(n,e),{prefix:e.prefix});P(o,t)}function Q(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=$(T[n]||T.header1);b("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,c=s;for(;c>0&&r[c-1]!==` +`),processed:n}}function F(o,e){return e?"- ":`${o+1}. `}function tt(o,e){let t,n,i;return o.orderedList?(t=ae(e),n=le(t.text),i=n.text):(t=le(e),n=ae(t.text),i=n.text),[t,n,i]}function nt(o,e){let t=o.selectionStart===o.selectionEnd,n=o.selectionStart,i=o.selectionEnd;pe(o);let r=o.value.slice(o.selectionStart,o.selectionEnd),[s,a,c]=tt(e,r),d=c.split(` +`).map((f,v)=>`${F(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+F(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+F(y,!e.unorderedList).length,0);if(s.processed)return t?(n=Math.max(n-F(0,e.unorderedList).length,0),i=n):(n=o.selectionStart,i=o.selectionEnd-l),{text:c,selectionStart:n,selectionEnd:i};let{newlinesToAppend:h,newlinesToPrepend:m}=Z(o),g=h+d.join(` +`)+m;return t?(n=Math.max(n+F(0,e.unorderedList).length+h.length,0),i=n):a.processed?(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l-p):(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l),{text:g,selectionStart:n,selectionEnd:i}}function ue(o,e){let t=V(o,n=>nt(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),h=e.orderedList&&l||e.unorderedList&&p;if(i===r)if(h){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(i-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:i+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:i+m}}else if(h){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(r-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:r+m}}}});P(o,t)}function ot(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` +`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(c,d);if(l.includes("**")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("**"),g=h.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("_"),g=h.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100));p.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("["),g=h.indexOf("]");m!==-1&&g!==-1&&i.slice(n+g+1,n+g+10).startsWith("(")&&e.push("link")}return e}function he(o){if(!o||o.disabled||o.readOnly)return;b("toggleBold","Starting"),R(o,"Before");let e=$(T.bold),t=U(o,e);ce(t),P(o,t),R(o,"After")}function me(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.italic),t=U(o,e);P(o,t)}function fe(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.code),t=U(o,e);P(o,t)}function ge(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=$(T.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);P(o,r)}function ve(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.bulletList);ue(o,e)}function ye(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.numberedList);ue(o,e)}function be(o){if(!o||o.disabled||o.readOnly)return;b("toggleQuote","Starting"),R(o,"Initial");let e=$(T.quote),t=V(o,n=>de(n,e),{prefix:e.prefix});ce(t),P(o,t),R(o,"Final")}function J(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.taskList),t=V(o,n=>de(n,e),{prefix:e.prefix});P(o,t)}function Q(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=$(T[n]||T.header1);b("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,c=s;for(;c>0&&r[c-1]!==` `;)c--;let d=a;for(;d{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):h>0?(b("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=i.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=i.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:i.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let B=Math.max(y-m,x);return b("insertHeader",` - Removing header, adjusting by -${m}`),{start:B,end:y===w?B:Math.max(w-m,x)}}else if(m>0){let B=i.prefix.length-m;return b("insertHeader",` - Replacing header, adjusting by ${B}`),{start:y+B,end:w+B}}else return b("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:y+i.prefix.length,end:w+i.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),P(o,f)}function we(o){Q(o,1,!0)}function xe(o){Q(o,2,!0)}function ke(o){Q(o,3,!0)}function Le(o){return ot(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Le)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` @@ -939,7 +939,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! `,Ne=` -`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Ee,title:"Bold (Ctrl+B)",action:({editor:o})=>{he(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:$e,title:"Inline Code",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ce,title:"Heading 1",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Me,title:"Heading 3",action:({editor:o})=>{ke(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:Ie,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Be,title:"Numbered List",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:_e,title:"Task List",action:({editor:o})=>{J&&(J(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function je(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function ze(o){let e=o||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function rt(o,e){let t=ze(o),n=ze(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(u.prototype);return s._init(r,t),r.overTypeInstance=s,u.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++u.instanceCount,this.initialized=!1,u.injectStyles(),u.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new j(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||u.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=_(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||u.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=_(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=je(N),this.options.toolbarButtons&&Object.assign(this.actionsById,je(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;t`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Ee,title:"Bold (Ctrl+B)",action:({editor:o})=>{he(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:$e,title:"Inline Code",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ce,title:"Heading 1",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Me,title:"Heading 3",action:({editor:o})=>{ke(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:Ie,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Be,title:"Numbered List",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:_e,title:"Task List",action:({editor:o})=>{J&&(J(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function ze(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function je(o){let e=o||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function rt(o,e){let t=je(o),n=je(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(u.prototype);return s._init(r,t),r.overTypeInstance=s,u.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++u.instanceCount,this.initialized=!1,u.injectStyles(),u.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||u.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=_(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||u.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=_(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=ze(N),this.options.toolbarButtons&&Object.assign(this.actionsById,ze(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tp.replace(/^ /,"")).join(` `);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else if(n!==i){let s=r.substring(0,n),a=r.substring(n,i),c=r.substring(i),l=a.split(` @@ -948,7 +948,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! `+t),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}splitListItem(e,t){let n=e.content.substring(t-e.markerEndPos);this.textarea.setSelectionRange(t,e.lineEnd),document.execCommand("delete");let i=S.createNewListItem(e);document.execCommand("insertText",!1,` `+i+n);let r=this.textarea.selectionStart-n.length;this.textarea.setSelectionRange(r,r),this.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}scheduleNumberedListUpdate(){this.numberUpdateTimeout&&clearTimeout(this.numberUpdateTimeout),this.numberUpdateTimeout=setTimeout(()=>{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,n=S.renumberLists(e);if(n!==e){let i=0,r=e.split(` `),s=n.split(` -`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&rt(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(K("auto"));else{let t=typeof e=="string"?M(e):e,n=typeof t=="string"?t:t.name;if(n&&this.container.setAttribute("data-theme",n),t&&t.colors){let i=_(t.colors);this.container.style.cssText+=i}this.updatePreview()}return this}_applyTheme(e){let t=M(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}_setupAuto(){window.matchMedia&&(u._autoInstances.add(this),u._mq||(u._mq=window.matchMedia("(prefers-color-scheme: dark)"),u._mqListener=e=>{let t=e.matches?"cave":"solar";u._autoInstances.forEach(n=>n._applyTheme(t))},u._mq.addEventListener?u._mq.addEventListener("change",u._mqListener):u._mq.addListener&&u._mq.addListener(u._mqListener)))}_cleanupAuto(){u._autoInstances.delete(this),u._autoInstances.size===0&&u._mq&&(u._mq.removeEventListener?u._mq.removeEventListener("change",u._mqListener):u._mq.removeListener&&u._mq.removeListener(u._mqListener),u._mq=null,u._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` +`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&rt(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(K("auto"));else{let t=typeof e=="string"?M(e):e,n=t.name||e;n&&this.container.setAttribute("data-theme",n),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}return this}_applyTheme(e){let t=M(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}_setupAuto(){var e;window.matchMedia&&(u._autoInstances.add(this),u._mq||(u._mq=window.matchMedia("(prefers-color-scheme: dark)"),u._mqListener=t=>{let n=t.matches?"cave":"solar";u._autoInstances.forEach(i=>i._applyTheme(n))},(e=u._mq.addEventListener||u._mq.addListener)==null||e.call(u._mq,"change",u._mqListener)))}_cleanupAuto(){var e;u._autoInstances.delete(this),u._autoInstances.size===0&&u._mq&&((e=u._mq.removeEventListener||u._mq.removeListener)==null||e.call(u._mq,"change",u._mqListener),u._mq=null,u._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` `),n=e.length,i=e.split(/\s+/).filter(l=>l.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(` `),c=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:n,words:i,lines:t.length,line:c,column:d}):this.statsBar.innerHTML=`
    @@ -956,7 +956,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! ${n} chars, ${i} words, ${t.length} lines
    Line ${c}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,u.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new u(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=u._parseDataValue(s.value)}return new u(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||u.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=u.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(u.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=u.currentTheme||A,i=ne({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),u.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let n=document.querySelectorAll(".overtype-container"),i=document.querySelectorAll(".overtype-wrapper");n.forEach(r=>{t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)}),i.forEach(r=>{var s;r.closest(".overtype-container")||(t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)),(s=r._instance)==null||s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{var s,a,c,d;t?((s=r.setAttribute)==null||s.call(r,"theme","auto"),(a=r.setAttribute)==null||a.call(r,"data-resolved-theme",e)):(c=r.setAttribute)==null||c.call(r,"theme",e),(d=r.refreshTheme)==null||d.call(r)})}static setTheme(e,t=null){if(u._cleanupGlobalAuto(),e==="auto")u._setupGlobalAuto(),u._applyGlobalTheme(K("auto"),t,!0);else{let n=typeof e=="string"?M(e):e;t&&(n=G(n,t)),u.currentTheme=n,u.injectStyles(!0);let i=n.name||e;i&&u._updateThemeAttrs(i)}}static _applyGlobalTheme(e,t=null,n=!1){let i=M(e);t&&(i=G(i,t)),u.currentTheme=i,u.injectStyles(!0),u._updateThemeAttrs(e,n)}static _setupGlobalAuto(){!window.matchMedia||u._globalAutoMq||(u._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),u._globalAutoListener=e=>{u._applyGlobalTheme(e.matches?"cave":"solar",null,!0)},u._globalAutoMq.addEventListener?u._globalAutoMq.addEventListener("change",u._globalAutoListener):u._globalAutoMq.addListener&&u._globalAutoMq.addListener(u._globalAutoListener))}static _cleanupGlobalAuto(){u._globalAutoMq&&u._globalAutoListener&&(u._globalAutoMq.removeEventListener?u._globalAutoMq.removeEventListener("change",u._globalAutoListener):u._globalAutoMq.removeListener&&u._globalAutoMq.removeListener(u._globalAutoListener),u._globalAutoMq=null,u._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){u.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),u.globalListenersInitialized=!0)}};E(u,"instances",new WeakMap),E(u,"stylesInjected",!1),E(u,"globalListenersInitialized",!1),E(u,"instanceCount",0),E(u,"_mq",null),E(u,"_mqListener",null),E(u,"_autoInstances",new Set),E(u,"_globalAutoMq",null),E(u,"_globalAutoListener",null);var I=u;I.MarkdownParser=S;I.ShortcutsManager=j;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var st=I;return De(at);})(); + `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,u.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new u(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=u._parseDataValue(s.value)}return new u(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||u.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=u.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(u.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=u.currentTheme||A,i=ne({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),u.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let n=document.querySelectorAll(".overtype-container"),i=document.querySelectorAll(".overtype-wrapper");n.forEach(r=>{t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)}),i.forEach(r=>{var s;r.closest(".overtype-container")||(t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)),(s=r._instance)==null||s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{var s,a,c,d;t?((s=r.setAttribute)==null||s.call(r,"theme","auto"),(a=r.setAttribute)==null||a.call(r,"data-resolved-theme",e)):(c=r.setAttribute)==null||c.call(r,"theme",e),(d=r.refreshTheme)==null||d.call(r)})}static setTheme(e,t=null){if(u._cleanupGlobalAuto(),e==="auto")u._setupGlobalAuto(),u._applyGlobalTheme(K("auto"),t,!0);else{let n=typeof e=="string"?M(e):e;t&&(n=G(n,t)),u.currentTheme=n,u.injectStyles(!0);let i=n.name||e;i&&u._updateThemeAttrs(i)}}static _applyGlobalTheme(e,t=null,n=!1){let i=M(e);t&&(i=G(i,t)),u.currentTheme=i,u.injectStyles(!0),u._updateThemeAttrs(e,n)}static _setupGlobalAuto(){var e;!window.matchMedia||u._globalAutoMq||(u._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),u._globalAutoListener=t=>{u._applyGlobalTheme(t.matches?"cave":"solar",null,!0)},(e=u._globalAutoMq.addEventListener||u._globalAutoMq.addListener)==null||e.call(u._globalAutoMq,"change",u._globalAutoListener))}static _cleanupGlobalAuto(){var e;u._globalAutoMq&&u._globalAutoListener&&((e=u._globalAutoMq.removeEventListener||u._globalAutoMq.removeListener)==null||e.call(u._globalAutoMq,"change",u._globalAutoListener),u._globalAutoMq=null,u._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){u.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),u.globalListenersInitialized=!0)}};E(u,"instances",new WeakMap),E(u,"stylesInjected",!1),E(u,"globalListenersInitialized",!1),E(u,"instanceCount",0),E(u,"_mq",null),E(u,"_mqListener",null),E(u,"_autoInstances",new Set),E(u,"_globalAutoMq",null),E(u,"_globalAutoListener",null);var I=u;I.MarkdownParser=S;I.ShortcutsManager=z;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var st=I;return De(at);})(); /** * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment * @version 1.0.0 diff --git a/src/overtype.js b/src/overtype.js index 38f4a21..42d117f 100644 --- a/src/overtype.js +++ b/src/overtype.js @@ -1036,34 +1036,24 @@ class OverType { * @returns {this} Returns this for chaining */ setTheme(theme) { - // Clean up existing auto theme listener if any this._cleanupAuto(); - - // Update instance theme this.instanceTheme = theme; - // Handle auto theme if (theme === 'auto') { this._setupAuto(); - // Apply the initial resolved theme this._applyTheme(resolveAutoTheme('auto')); } else { - // Get theme object for non-auto themes const themeObj = typeof theme === 'string' ? getTheme(theme) : theme; - const themeName = typeof themeObj === 'string' ? themeObj : themeObj.name; + const themeName = themeObj.name || theme; - // Update container theme attribute if (themeName) { this.container.setAttribute('data-theme', themeName); } - // Apply CSS variables to container for instance override - if (themeObj && themeObj.colors) { - const cssVars = themeToCSSVars(themeObj.colors); - this.container.style.cssText += cssVars; + if (themeObj?.colors) { + this.container.style.cssText += themeToCSSVars(themeObj.colors); } - // Update preview to reflect new theme this.updatePreview(); } @@ -1073,21 +1063,16 @@ class OverType { /** * Apply a resolved theme name (used by auto theme) * @private - * @param {string} themeName - Resolved theme name */ _applyTheme(themeName) { const themeObj = getTheme(themeName); - - // Update container with resolved theme, but keep auto in data-theme for tracking this.container.setAttribute('data-theme', 'auto'); this.container.setAttribute('data-resolved-theme', themeName); - // Apply CSS variables if (themeObj?.colors) { this.container.style.cssText += themeToCSSVars(themeObj.colors); } - // Update preview to reflect new theme this.updatePreview(); } @@ -1098,23 +1083,19 @@ class OverType { _setupAuto() { if (!window.matchMedia) return; - // Add this instance to the global auto instances set OverType._autoInstances.add(this); - // Setup global listener if not already setup if (!OverType._mq) { OverType._mq = window.matchMedia('(prefers-color-scheme: dark)'); OverType._mqListener = (e) => { const theme = e.matches ? 'cave' : 'solar'; - // Notify all auto-themed instances OverType._autoInstances.forEach(inst => inst._applyTheme(theme)); }; - if (OverType._mq.addEventListener) { - OverType._mq.addEventListener('change', OverType._mqListener); - } else if (OverType._mq.addListener) { - OverType._mq.addListener(OverType._mqListener); - } + // Use modern addEventListener or fallback to legacy addListener + (OverType._mq.addEventListener || OverType._mq.addListener)?.call( + OverType._mq, 'change', OverType._mqListener + ); } } @@ -1123,16 +1104,13 @@ class OverType { * @private */ _cleanupAuto() { - // Remove this instance from the auto instances set OverType._autoInstances.delete(this); - // If no more auto instances, cleanup the global listener if (OverType._autoInstances.size === 0 && OverType._mq) { - if (OverType._mq.removeEventListener) { - OverType._mq.removeEventListener('change', OverType._mqListener); - } else if (OverType._mq.removeListener) { - OverType._mq.removeListener(OverType._mqListener); - } + // Use modern removeEventListener or fallback to legacy removeListener + (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call( + OverType._mq, 'change', OverType._mqListener + ); OverType._mq = null; OverType._mqListener = null; } @@ -1579,11 +1557,10 @@ class OverType { OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true); }; - if (OverType._globalAutoMq.addEventListener) { - OverType._globalAutoMq.addEventListener('change', OverType._globalAutoListener); - } else if (OverType._globalAutoMq.addListener) { - OverType._globalAutoMq.addListener(OverType._globalAutoListener); - } + // Use modern addEventListener or fallback to legacy addListener + (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call( + OverType._globalAutoMq, 'change', OverType._globalAutoListener + ); } /** @@ -1592,11 +1569,10 @@ class OverType { */ static _cleanupGlobalAuto() { if (OverType._globalAutoMq && OverType._globalAutoListener) { - if (OverType._globalAutoMq.removeEventListener) { - OverType._globalAutoMq.removeEventListener('change', OverType._globalAutoListener); - } else if (OverType._globalAutoMq.removeListener) { - OverType._globalAutoMq.removeListener(OverType._globalAutoListener); - } + // Use modern removeEventListener or fallback to legacy removeListener + (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call( + OverType._globalAutoMq, 'change', OverType._globalAutoListener + ); OverType._globalAutoMq = null; OverType._globalAutoListener = null; } diff --git a/src/themes.js b/src/themes.js index 30445b5..e02aeaf 100644 --- a/src/themes.js +++ b/src/themes.js @@ -141,8 +141,11 @@ export function resolveAutoTheme(themeName) { * @returns {string} 'dark' or 'light' */ export function getSystemColorScheme() { - const isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; - return isDarkMode ? 'dark' : 'light'; + // Reuse cached media query if available + if (!_mq && window.matchMedia) { + _mq = window.matchMedia('(prefers-color-scheme: dark)'); + } + return _mq?.matches ? 'dark' : 'light'; } /** From ccd9e419a802b3e5d8611faf0064b58ba84e42ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:29:22 +0000 Subject: [PATCH 6/8] Extract setTheme helper and optimize web component updates Co-authored-by: dido739 <152557154+dido739@users.noreply.github.com> --- dist/overtype-webcomponent.esm.js | 32 +++++--------- dist/overtype-webcomponent.js | 32 +++++--------- dist/overtype-webcomponent.min.js | 24 +++++------ dist/overtype.cjs | 32 +++++--------- dist/overtype.esm.js | 32 +++++--------- dist/overtype.esm.js.map | 4 +- dist/overtype.js | 32 +++++--------- dist/overtype.js.map | 4 +- dist/overtype.min.js | 70 +++++++++++++++---------------- src/overtype.js | 32 ++++---------- 10 files changed, 115 insertions(+), 179 deletions(-) diff --git a/dist/overtype-webcomponent.esm.js b/dist/overtype-webcomponent.esm.js index 2e94000..6574aa2 100644 --- a/dist/overtype-webcomponent.esm.js +++ b/dist/overtype-webcomponent.esm.js @@ -4402,37 +4402,27 @@ var _OverType = class _OverType { * @private */ static _updateThemeAttrs(themeName, isAuto = false) { - const containers = document.querySelectorAll(".overtype-container"); - const wrappers = document.querySelectorAll(".overtype-wrapper"); - containers.forEach((el) => { + const setTheme = (el) => { if (isAuto) { el.setAttribute("data-theme", "auto"); el.setAttribute("data-resolved-theme", themeName); } else { el.setAttribute("data-theme", themeName); } - }); - wrappers.forEach((wrapper) => { + }; + document.querySelectorAll(".overtype-container").forEach(setTheme); + document.querySelectorAll(".overtype-wrapper").forEach((w) => { var _a; - if (!wrapper.closest(".overtype-container")) { - if (isAuto) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } else { - wrapper.setAttribute("data-theme", themeName); - } - } - (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + if (!w.closest(".overtype-container")) + setTheme(w); + (_a = w._instance) == null ? void 0 : _a.updatePreview(); }); document.querySelectorAll("overtype-editor").forEach((wc) => { - var _a, _b, _c, _d; - if (isAuto) { - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + var _a, _b, _c; + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); - } else { - (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); - } - (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); }); } /** diff --git a/dist/overtype-webcomponent.js b/dist/overtype-webcomponent.js index c1858f6..1d237c8 100644 --- a/dist/overtype-webcomponent.js +++ b/dist/overtype-webcomponent.js @@ -4425,37 +4425,27 @@ ${blockSuffix}` : suffix; * @private */ static _updateThemeAttrs(themeName, isAuto = false) { - const containers = document.querySelectorAll(".overtype-container"); - const wrappers = document.querySelectorAll(".overtype-wrapper"); - containers.forEach((el) => { + const setTheme = (el) => { if (isAuto) { el.setAttribute("data-theme", "auto"); el.setAttribute("data-resolved-theme", themeName); } else { el.setAttribute("data-theme", themeName); } - }); - wrappers.forEach((wrapper) => { + }; + document.querySelectorAll(".overtype-container").forEach(setTheme); + document.querySelectorAll(".overtype-wrapper").forEach((w) => { var _a; - if (!wrapper.closest(".overtype-container")) { - if (isAuto) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } else { - wrapper.setAttribute("data-theme", themeName); - } - } - (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + if (!w.closest(".overtype-container")) + setTheme(w); + (_a = w._instance) == null ? void 0 : _a.updatePreview(); }); document.querySelectorAll("overtype-editor").forEach((wc) => { - var _a, _b, _c, _d; - if (isAuto) { - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + var _a, _b, _c; + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); - } else { - (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); - } - (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); }); } /** diff --git a/dist/overtype-webcomponent.min.js b/dist/overtype-webcomponent.min.js index 2658e96..b34a4ba 100644 --- a/dist/overtype-webcomponent.min.js +++ b/dist/overtype-webcomponent.min.js @@ -12,7 +12,7 @@ var OverTypeEditor=(()=>{var F=Object.defineProperty;var Ve=Object.getOwnPropert `),p=s.slice(3).trim(),u=p?` class="language-${p}"`:"",m=l,g=t||this.codeHighlighter;if(g)try{let v=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=g(v,p);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(m=y)}catch(v){console.warn("Code highlighting failed:",v)}let f=`
    ${s}
    `;return f+=`
    ${m}
    `,f+=`
    ${c}
    `,f}),i}static getListContext(e,t){let i=e.split(` `),o=0,r=0,s=0;for(let u=0;u=t){r=u,s=o;break}o+=m+1}let a=i[r],c=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:c,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:c,markerEndPos:s+l[1].length+l[2].length+1};let p=a.match(this.LIST_PATTERNS.numbered);return p?{inList:!0,listType:"numbered",indent:p[1],marker:parseInt(p[2]),content:p[3],lineStart:s,lineEnd:c,markerEndPos:s+p[1].length+p[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:c,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` `),i=new Map,o=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let c=a[1],d=c.length,l=a[3];o||i.clear();let p=(i.get(d)||0)+1;i.set(d,p);for(let[u]of i)u>d&&i.delete(u);return o=!0,`${c}${p}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(o=!1,i.clear()),s}).join(` -`)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let o=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(o="toggleBold");break;case"i":e.shiftKey||(o="toggleItalic");break;case"k":e.shiftKey||(o="insertLink");break;case"7":e.shiftKey&&(o="toggleNumberedList");break;case"8":e.shiftKey&&(o="toggleBulletList");break}return o?(e.preventDefault(),this.editor.performAction(o,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ie={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},Ze={name:"auto",colors:A.colors},ne={solar:A,cave:ie,auto:Ze,light:A,dark:ie};function _(n){return typeof n=="string"?{...ne[n]||ne.solar,name:n}:n}var O=null;function Z(n){return n!=="auto"?n:(!O&&window.matchMedia&&(O=window.matchMedia("(prefers-color-scheme: dark)")),O!=null&&O.matches?"cave":"solar")}function B(n){let e=[];for(let[t,i]of Object.entries(n)){let o=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${o}: ${i};`)}return e.join(` +`)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let o=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(o="toggleBold");break;case"i":e.shiftKey||(o="toggleItalic");break;case"k":e.shiftKey||(o="insertLink");break;case"7":e.shiftKey&&(o="toggleNumberedList");break;case"8":e.shiftKey&&(o="toggleBulletList");break}return o?(e.preventDefault(),this.editor.performAction(o,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ie={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},Ze={name:"auto",colors:A.colors},ne={solar:A,cave:ie,auto:Ze,light:A,dark:ie};function _(n){return typeof n=="string"?{...ne[n]||ne.solar,name:n}:n}var N=null;function Z(n){return n!=="auto"?n:(!N&&window.matchMedia&&(N=window.matchMedia("(prefers-color-scheme: dark)")),N!=null&&N.matches?"cave":"solar")}function B(n){let e=[];for(let[t,i]of Object.entries(n)){let o=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${o}: ${i};`)}return e.join(` `)}function J(n,e={}){return{...n,colors:{...n.colors,...e}}}function R(n={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:i='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:o="20px",theme:r=null,mobile:s={}}=n,a=Object.keys(s).length>0?` @media (max-width: 640px) { .overtype-wrapper .overtype-input, @@ -861,7 +861,7 @@ var OverTypeEditor=(()=>{var F=Object.defineProperty;var Ve=Object.getOwnPropert } ${a} - `}var Je=Object.defineProperty,oe=Object.getOwnPropertySymbols,Qe=Object.prototype.hasOwnProperty,Xe=Object.prototype.propertyIsEnumerable,re=(n,e,t)=>e in n?Je(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,se=(n,e)=>{for(var t in e||(e={}))Qe.call(e,t)&&re(n,t,e[t]);if(oe)for(var t of oe(e))Xe.call(e,t)&&re(n,t,e[t]);return n},C={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Ye(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function M(n){return se(se({},Ye()),n)}var q=!1;function et(){return q}function b(n,e,t){q&&(console.group(`\u{1F50D} ${n}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function V(n,e){if(!q)return;let t=n.value.slice(n.selectionStart,n.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let i=n.value.slice(Math.max(0,n.selectionStart-10),n.selectionStart),o=n.value.slice(n.selectionEnd,Math.min(n.value.length,n.selectionEnd+10));console.log("Context:",JSON.stringify(i)+"[SELECTION]"+JSON.stringify(o)),console.groupEnd()}function pe(n){q&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(n.text)),console.log("New selection:",`${n.selectionStart}-${n.selectionEnd}`),console.groupEnd())}var H=null;function $(n,{text:e,selectionStart:t,selectionEnd:i}){let o=et();o&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",i)),n.focus();let r=n.selectionStart,s=n.selectionEnd,a=n.value.slice(0,r),c=n.value.slice(s);o&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(n.value.slice(r,s))));let d=n.value,l=r!==s;if(H===null||H===!0){n.contentEditable="true";try{H=document.execCommand("insertText",!1,e),o&&console.log("execCommand returned:",H,"for text with",e.split(` + `}var Je=Object.defineProperty,oe=Object.getOwnPropertySymbols,Qe=Object.prototype.hasOwnProperty,Xe=Object.prototype.propertyIsEnumerable,re=(n,e,t)=>e in n?Je(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t,se=(n,e)=>{for(var t in e||(e={}))Qe.call(e,t)&&re(n,t,e[t]);if(oe)for(var t of oe(e))Xe.call(e,t)&&re(n,t,e[t]);return n},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Ye(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function M(n){return se(se({},Ye()),n)}var q=!1;function et(){return q}function b(n,e,t){q&&(console.group(`\u{1F50D} ${n}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function V(n,e){if(!q)return;let t=n.value.slice(n.selectionStart,n.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let i=n.value.slice(Math.max(0,n.selectionStart-10),n.selectionStart),o=n.value.slice(n.selectionEnd,Math.min(n.value.length,n.selectionEnd+10));console.log("Context:",JSON.stringify(i)+"[SELECTION]"+JSON.stringify(o)),console.groupEnd()}function pe(n){q&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(n.text)),console.log("New selection:",`${n.selectionStart}-${n.selectionEnd}`),console.groupEnd())}var H=null;function $(n,{text:e,selectionStart:t,selectionEnd:i}){let o=et();o&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${n.selectionStart}-${n.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",i)),n.focus();let r=n.selectionStart,s=n.selectionEnd,a=n.value.slice(0,r),c=n.value.slice(s);o&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(n.value.slice(r,s))));let d=n.value,l=r!==s;if(H===null||H===!0){n.contentEditable="true";try{H=document.execCommand("insertText",!1,e),o&&console.log("execCommand returned:",H,"for text with",e.split(` `).length,"lines")}catch(p){H=!1,o&&console.log("execCommand threw error:",p)}n.contentEditable="false"}if(o&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let p=a+e+c,u=n.value;o&&(console.log("Expected length:",p.length),console.log("Actual length:",u.length)),u!==p&&o&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(p.slice(0,100))),console.log("Actual:",JSON.stringify(u.slice(0,100))))}if(!H)if(o&&console.log("Using manual insertion"),n.value===d){o&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(p){}n.value=a+e+c;try{document.execCommand("ms-endUndoUnit")}catch(p){}n.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else o&&console.log("Value was changed by execCommand, skipping manual insertion");o&&console.log("Setting selection range:",t,i),t!=null&&i!=null?n.setSelectionRange(t,i):n.setSelectionRange(r,n.selectionEnd),o&&(console.log("Final value length:",n.value.length),console.groupEnd())}function ae(n){return n.trim().split(` `).length>1}function tt(n,e){let t=e;for(;n[t]&&n[t-1]!=null&&!n[t-1].match(/\s/);)t--;return t}function it(n,e,t){let i=e,o=t?/\n/:/\s/;for(;n[i]&&!n[i].match(o);)i++;return i}function de(n){let e=n.value.split(` `),t=0;for(let i=0;i=t&&n.selectionStart=t&&n.selectionEnd{var F=Object.defineProperty;var Ve=Object.getOwnPropert `;)a--;if(r){let d=i;for(;d0?`${s} `:o,y=ae(f)&&a&&a.length>0?` -${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(v=` ${v}`)}f=nt(n,v,y,e.multiline);let w=n.selectionStart,x=n.selectionEnd,I=c&&c.length>0&&y.indexOf(c)>-1&&f.length>0;if(p){let L=Q(n);t=L.newlinesToAppend,i=L.newlinesToPrepend,v=t+o,y+=i}if(f.startsWith(v)&&f.endsWith(y)){let L=f.slice(v.length,f.length-y.length);if(m===g){let T=m-v.length;T=Math.max(T,w),T=Math.min(T,w+L.length),w=x=T}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if(I)if(l&&l.length>0&&f.match(l)){y=y.replace(c,f);let L=v+y;return w=x=w+v.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;return w=w+v.length+f.length+y.indexOf(c),x=w+c.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;w=m+v.length,x=g+v.length;let T=f.match(/^\s*|\s*$/g);if(u&&T){let ee=T[0]||"",te=T[1]||"";L=ee+v+f.trim()+y+te,w+=ee.length,x-=te.length}return{text:L,selectionStart:w,selectionEnd:x}}}function he(n,e){let{prefix:t,suffix:i,surroundWithNewlines:o}=e,r=n.value.slice(n.selectionStart,n.selectionEnd),s=n.selectionStart,a=n.selectionEnd,c=r.split(` +${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(v=` ${v}`)}f=nt(n,v,y,e.multiline);let w=n.selectionStart,x=n.selectionEnd,I=c&&c.length>0&&y.indexOf(c)>-1&&f.length>0;if(p){let L=Q(n);t=L.newlinesToAppend,i=L.newlinesToPrepend,v=t+o,y+=i}if(f.startsWith(v)&&f.endsWith(y)){let L=f.slice(v.length,f.length-y.length);if(m===g){let C=m-v.length;C=Math.max(C,w),C=Math.min(C,w+L.length),w=x=C}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if(I)if(l&&l.length>0&&f.match(l)){y=y.replace(c,f);let L=v+y;return w=x=w+v.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;return w=w+v.length+f.length+y.indexOf(c),x=w+c.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;w=m+v.length,x=g+v.length;let C=f.match(/^\s*|\s*$/g);if(u&&C){let ee=C[0]||"",te=C[1]||"";L=ee+v+f.trim()+y+te,w+=ee.length,x-=te.length}return{text:L,selectionStart:w,selectionEnd:x}}}function he(n,e){let{prefix:t,suffix:i,surroundWithNewlines:o}=e,r=n.value.slice(n.selectionStart,n.selectionEnd),s=n.selectionStart,a=n.selectionEnd,c=r.split(` `);if(c.every(l=>l.startsWith(t)&&(!i||l.endsWith(i))))r=c.map(l=>{let p=l.slice(t.length);return i&&(p=p.slice(0,p.length-i.length)),p}).join(` `),a=s+r.length;else if(r=c.map(l=>t+l+(i||"")).join(` `),o){let{newlinesToAppend:l,newlinesToPrepend:p}=Q(n);s+=l.length,a=s+r.length,r=l+r+p}return{text:r,selectionStart:s,selectionEnd:a}}function le(n){let e=n.split(` `),t=/^\d+\.\s+/,i=e.every(r=>t.test(r)),o=e;return i&&(o=e.map(r=>r.replace(t,""))),{text:o.join(` `),processed:i}}function ce(n){let e=n.split(` `),t="- ",i=e.every(r=>r.startsWith(t)),o=e;return i&&(o=e.map(r=>r.slice(t.length))),{text:o.join(` -`),processed:i}}function N(n,e){return e?"- ":`${n+1}. `}function ot(n,e){let t,i,o;return n.orderedList?(t=le(e),i=ce(t.text),o=i.text):(t=ce(e),i=le(t.text),o=i.text),[t,i,o]}function rt(n,e){let t=n.selectionStart===n.selectionEnd,i=n.selectionStart,o=n.selectionEnd;de(n);let r=n.value.slice(n.selectionStart,n.selectionEnd),[s,a,c]=ot(e,r),d=c.split(` -`).map((f,v)=>`${N(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+N(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+N(y,!e.unorderedList).length,0);if(s.processed)return t?(i=Math.max(i-N(0,e.unorderedList).length,0),o=i):(i=n.selectionStart,o=n.selectionEnd-l),{text:c,selectionStart:i,selectionEnd:o};let{newlinesToAppend:u,newlinesToPrepend:m}=Q(n),g=u+d.join(` -`)+m;return t?(i=Math.max(i+N(0,e.unorderedList).length+u.length,0),o=i):a.processed?(i=Math.max(n.selectionStart+u.length,0),o=n.selectionEnd+u.length+l-p):(i=Math.max(n.selectionStart+u.length,0),o=n.selectionEnd+u.length+l),{text:g,selectionStart:i,selectionEnd:o}}function ue(n,e){let t=U(n,i=>rt(i,e),{adjustSelection:(i,o,r,s)=>{let a=n.value.slice(s,n.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),u=e.orderedList&&l||e.unorderedList&&p;if(o===r)if(u){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(o-g,s),end:Math.max(o-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:o+v}}else{let m=e.unorderedList?2:3;return{start:o+m,end:o+m}}else if(u){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(o-g,s),end:Math.max(r-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:o+m,end:r+m}}}});$(n,t)}function st(n){if(!n)return[];let e=[],{selectionStart:t,selectionEnd:i,value:o}=n,r=o.split(` -`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(o.length,i+10),l=o.slice(c,d);if(l.includes("**")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("**"),g=u.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("_"),g=u.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100));p.includes("`")&&u.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("["),g=u.indexOf("]");m!==-1&&g!==-1&&o.slice(i+g+1,i+g+10).startsWith("(")&&e.push("link")}return e}function me(n){if(!n||n.disabled||n.readOnly)return;b("toggleBold","Starting"),V(n,"Before");let e=M(C.bold),t=D(n,e);pe(t),$(n,t),V(n,"After")}function fe(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.italic),t=D(n,e);$(n,t)}function ge(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.code),t=D(n,e);$(n,t)}function ve(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),i=M(C.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(i.suffix=`](${t})`,i.replaceNext=""):e.url&&(i.suffix=`](${e.url})`,i.replaceNext=""),e.text&&!t){let s=n.selectionStart;n.value=n.value.slice(0,s)+e.text+n.value.slice(s),n.selectionStart=s,n.selectionEnd=s+e.text.length}let r=D(n,i);$(n,r)}function ye(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.bulletList);ue(n,e)}function be(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.numberedList);ue(n,e)}function we(n){if(!n||n.disabled||n.readOnly)return;b("toggleQuote","Starting"),V(n,"Initial");let e=M(C.quote),t=U(n,i=>he(i,e),{prefix:e.prefix});pe(t),$(n,t),V(n,"Final")}function X(n){if(!n||n.disabled||n.readOnly)return;let e=M(C.taskList),t=U(n,i=>he(i,e),{prefix:e.prefix});$(n,t)}function Y(n,e=1,t=!1){if(!n||n.disabled||n.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${n.selectionStart}-${n.selectionEnd}`);let i=`header${e===1?"1":e}`,o=M(C[i]||C.header1);b("insertHeader",`Style prefix: "${o.prefix}"`);let r=n.value,s=n.selectionStart,a=n.selectionEnd,c=s;for(;c>0&&r[c-1]!==` +`),processed:i}}function O(n,e){return e?"- ":`${n+1}. `}function ot(n,e){let t,i,o;return n.orderedList?(t=le(e),i=ce(t.text),o=i.text):(t=ce(e),i=le(t.text),o=i.text),[t,i,o]}function rt(n,e){let t=n.selectionStart===n.selectionEnd,i=n.selectionStart,o=n.selectionEnd;de(n);let r=n.value.slice(n.selectionStart,n.selectionEnd),[s,a,c]=ot(e,r),d=c.split(` +`).map((f,v)=>`${O(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+O(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+O(y,!e.unorderedList).length,0);if(s.processed)return t?(i=Math.max(i-O(0,e.unorderedList).length,0),o=i):(i=n.selectionStart,o=n.selectionEnd-l),{text:c,selectionStart:i,selectionEnd:o};let{newlinesToAppend:u,newlinesToPrepend:m}=Q(n),g=u+d.join(` +`)+m;return t?(i=Math.max(i+O(0,e.unorderedList).length+u.length,0),o=i):a.processed?(i=Math.max(n.selectionStart+u.length,0),o=n.selectionEnd+u.length+l-p):(i=Math.max(n.selectionStart+u.length,0),o=n.selectionEnd+u.length+l),{text:g,selectionStart:i,selectionEnd:o}}function ue(n,e){let t=U(n,i=>rt(i,e),{adjustSelection:(i,o,r,s)=>{let a=n.value.slice(s,n.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),u=e.orderedList&&l||e.unorderedList&&p;if(o===r)if(u){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(o-g,s),end:Math.max(o-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:o+v}}else{let m=e.unorderedList?2:3;return{start:o+m,end:o+m}}else if(u){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(o-g,s),end:Math.max(r-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:o+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:o+m,end:r+m}}}});$(n,t)}function st(n){if(!n)return[];let e=[],{selectionStart:t,selectionEnd:i,value:o}=n,r=o.split(` +`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(o.length,i+10),l=o.slice(c,d);if(l.includes("**")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("**"),g=u.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("_"),g=u.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100));p.includes("`")&&u.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=o.slice(Math.max(0,t-100),t),u=o.slice(i,Math.min(o.length,i+100)),m=p.lastIndexOf("["),g=u.indexOf("]");m!==-1&&g!==-1&&o.slice(i+g+1,i+g+10).startsWith("(")&&e.push("link")}return e}function me(n){if(!n||n.disabled||n.readOnly)return;b("toggleBold","Starting"),V(n,"Before");let e=M(T.bold),t=D(n,e);pe(t),$(n,t),V(n,"After")}function fe(n){if(!n||n.disabled||n.readOnly)return;let e=M(T.italic),t=D(n,e);$(n,t)}function ge(n){if(!n||n.disabled||n.readOnly)return;let e=M(T.code),t=D(n,e);$(n,t)}function ve(n,e={}){if(!n||n.disabled||n.readOnly)return;let t=n.value.slice(n.selectionStart,n.selectionEnd),i=M(T.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(i.suffix=`](${t})`,i.replaceNext=""):e.url&&(i.suffix=`](${e.url})`,i.replaceNext=""),e.text&&!t){let s=n.selectionStart;n.value=n.value.slice(0,s)+e.text+n.value.slice(s),n.selectionStart=s,n.selectionEnd=s+e.text.length}let r=D(n,i);$(n,r)}function ye(n){if(!n||n.disabled||n.readOnly)return;let e=M(T.bulletList);ue(n,e)}function be(n){if(!n||n.disabled||n.readOnly)return;let e=M(T.numberedList);ue(n,e)}function we(n){if(!n||n.disabled||n.readOnly)return;b("toggleQuote","Starting"),V(n,"Initial");let e=M(T.quote),t=U(n,i=>he(i,e),{prefix:e.prefix});pe(t),$(n,t),V(n,"Final")}function X(n){if(!n||n.disabled||n.readOnly)return;let e=M(T.taskList),t=U(n,i=>he(i,e),{prefix:e.prefix});$(n,t)}function Y(n,e=1,t=!1){if(!n||n.disabled||n.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${n.selectionStart}-${n.selectionEnd}`);let i=`header${e===1?"1":e}`,o=M(T[i]||T.header1);b("insertHeader",`Style prefix: "${o.prefix}"`);let r=n.value,s=n.selectionStart,a=n.selectionEnd,c=s;for(;c>0&&r[c-1]!==` `;)c--;let d=a;for(;d{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):u>0?(b("insertHeader",`ACTION: Replacing H${u} with H${e}`),x=o.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=o.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:o.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let I=Math.max(y-m,x);return b("insertHeader",` - Removing header, adjusting by -${m}`),{start:I,end:y===w?I:Math.max(w-m,x)}}else if(m>0){let I=o.prefix.length-m;return b("insertHeader",` - Replacing header, adjusting by ${I}`),{start:y+I,end:w+I}}else return b("insertHeader",` - Adding header, adjusting by +${o.prefix.length}`),{start:y+o.prefix.length,end:w+o.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),$(n,f)}function xe(n){Y(n,1,!0)}function ke(n){Y(n,2,!0)}function Le(n){Y(n,3,!0)}function Se(n){return st(n)}var W=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",i=>{i.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=i=>{i.preventDefault();let o=e.actionId||e.name;this.editor.performAction(o,i)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let i=this.createViewModeDropdown(e),o=e.getBoundingClientRect();i.style.position="absolute",i.style.top=`${o.bottom+5}px`,i.style.left=`${o.left}px`,document.body.appendChild(i),this.handleDocumentClick=r=>{!i.contains(r.target)&&!e.contains(r.target)&&(i.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let i=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],o=this.editor.container.dataset.mode||"normal";return i.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===o){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Se)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([i,o])=>{if(i==="viewMode")return;let r=!1;switch(i){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}o.classList.toggle("active",r),o.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var K=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:i,offset:o,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:i,offset:o,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` @@ -893,11 +893,11 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,i=this.findLinkAtPosition(t,e);i?(!this.currentLink||this.currentLink.url!==i.url||this.currentLink.index!==i.index)&&this.show(i):this.scheduleHide()}findLinkAtPosition(e,t){let i=/\[([^\]]+)\]\(([^)]+)\)/g,o,r=0;for(;(o=i.exec(e))!==null;){let s=o.index,a=o.index+o[0].length;if(t>=s&&t<=a)return{text:o[1],url:o[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let i=t.getBoundingClientRect();if(!(i.width===0||i.height===0))try{let{x:o,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${o}px`,top:`${r}px`,position:"absolute"})}catch(o){console.warn("Floating UI positioning failed:",o);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var _e=` -`,Ce=` +`,Te=` -`,Te=` +`,Ce=` `,Ae=` @@ -936,10 +936,10 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! -`,Oe=` +`,Ne=` -`;var k={bold:{name:"bold",actionId:"toggleBold",icon:_e,title:"Bold (Ctrl+B)",action:({editor:n})=>{me(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Ce,title:"Italic (Ctrl+I)",action:({editor:n})=>{fe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:Ie,title:"Inline Code",action:({editor:n})=>{ge(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:Me,title:"Insert Link",action:({editor:n})=>{ve(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Te,title:"Heading 1",action:({editor:n})=>{xe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:n})=>{ke(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:He,title:"Heading 3",action:({editor:n})=>{Le(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:n})=>{ye(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Pe,title:"Numbered List",action:({editor:n})=>{be(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:ze,title:"Task List",action:({editor:n})=>{X&&(X(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Be,title:"Quote",action:({editor:n})=>{we(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Oe,title:"View mode"}},j=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function Ne(n){let e={};return(n||[]).forEach(t=>{if(!t||t.name==="separator")return;let i=t.actionId||t.name;t.action&&(e[i]=t.action)}),e}function je(n){let e=n||j;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function lt(n,e){let t=je(n),i=je(e);if(t===null||i===null)return t!==i;if(t.length!==i.length)return!0;for(let o=0;o{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(h.prototype);return s._init(r,t),r.overTypeInstance=s,h.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++h.instanceCount,this.initialized=!1,h.injectStyles(),h.initGlobalListeners();let i=e.querySelector(".overtype-container"),o=e.querySelector(".overtype-wrapper");i||o?this._recoverFromDOM(i,o):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new K(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:i,colors:o,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let i=this.instanceTheme||h.currentTheme||A,o=typeof i=="string"?i:i.name;if(o&&this.container.setAttribute("data-theme",o),this.instanceTheme){let r=typeof this.instanceTheme=="string"?_(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=B(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||h.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let i=typeof this.instanceTheme=="string"?_(this.instanceTheme):this.instanceTheme;if(i&&i.colors){let o=B(i.colors);this.container.style.cssText+=o}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([i,o])=>{i==="className"||i==="class"?this.textarea.className+=" "+o:i==="style"&&typeof o=="object"?Object.assign(this.textarea.style,o):this.textarea.setAttribute(i,o)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||j;this.toolbar=new W(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=Ne(j),this.options.toolbarButtons&&Object.assign(this.actionsById,Ne(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,i=this._getCurrentLine(e,t),o=this.container.dataset.mode==="preview",r=S.parse(e,i,this.options.showActiveLineRaw,this.options.codeHighlighter,o);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;t`;var k={bold:{name:"bold",actionId:"toggleBold",icon:_e,title:"Bold (Ctrl+B)",action:({editor:n})=>{me(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:n})=>{fe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:Ie,title:"Inline Code",action:({editor:n})=>{ge(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:Me,title:"Insert Link",action:({editor:n})=>{ve(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ce,title:"Heading 1",action:({editor:n})=>{xe(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:n})=>{ke(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:He,title:"Heading 3",action:({editor:n})=>{Le(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:$e,title:"Bullet List",action:({editor:n})=>{ye(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Pe,title:"Numbered List",action:({editor:n})=>{be(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:ze,title:"Task List",action:({editor:n})=>{X&&(X(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Be,title:"Quote",action:({editor:n})=>{we(n.textarea),n.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},j=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function Oe(n){let e={};return(n||[]).forEach(t=>{if(!t||t.name==="separator")return;let i=t.actionId||t.name;t.action&&(e[i]=t.action)}),e}function je(n){let e=n||j;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function lt(n,e){let t=je(n),i=je(e);if(t===null||i===null)return t!==i;if(t.length!==i.length)return!0;for(let o=0;o{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(h.prototype);return s._init(r,t),r.overTypeInstance=s,h.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++h.instanceCount,this.initialized=!1,h.injectStyles(),h.initGlobalListeners();let i=e.querySelector(".overtype-container"),o=e.querySelector(".overtype-wrapper");i||o?this._recoverFromDOM(i,o):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new K(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:i,colors:o,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let i=this.instanceTheme||h.currentTheme||A,o=typeof i=="string"?i:i.name;if(o&&this.container.setAttribute("data-theme",o),this.instanceTheme){let r=typeof this.instanceTheme=="string"?_(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=B(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||h.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let i=typeof this.instanceTheme=="string"?_(this.instanceTheme):this.instanceTheme;if(i&&i.colors){let o=B(i.colors);this.container.style.cssText+=o}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([i,o])=>{i==="className"||i==="class"?this.textarea.className+=" "+o:i==="style"&&typeof o=="object"?Object.assign(this.textarea.style,o):this.textarea.setAttribute(i,o)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||j;this.toolbar=new W(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=Oe(j),this.options.toolbarButtons&&Object.assign(this.actionsById,Oe(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,i=this._getCurrentLine(e,t),o=this.container.dataset.mode==="preview",r=S.parse(e,i,this.options.showActiveLineRaw,this.options.codeHighlighter,o);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tp.replace(/^ /,"")).join(` `);document.execCommand?(this.textarea.setSelectionRange(i,o),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=i,this.textarea.selectionEnd=i+l.length)}else if(i!==o){let s=r.substring(0,i),a=r.substring(i,o),c=r.substring(o),l=a.split(` @@ -956,7 +956,7 @@ ${a}`:r;if(d){let L=n.value[n.selectionStart-1];n.selectionStart!==0&&L!=null&&! ${i} chars, ${o} words, ${t.length} lines
    Line ${c}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper,o=window.getComputedStyle(e),r=parseFloat(o.paddingTop),s=parseFloat(o.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,h.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new h(e,t)}static initFromData(e,t={}){let i=document.querySelectorAll(e);return Array.from(i).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=h._parseDataValue(s.value)}return new h(o,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||h.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=h.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(h.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=h.currentTheme||A,o=R({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),h.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let i=document.querySelectorAll(".overtype-container"),o=document.querySelectorAll(".overtype-wrapper");i.forEach(r=>{t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)}),o.forEach(r=>{var s;r.closest(".overtype-container")||(t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)),(s=r._instance)==null||s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{var s,a,c,d;t?((s=r.setAttribute)==null||s.call(r,"theme","auto"),(a=r.setAttribute)==null||a.call(r,"data-resolved-theme",e)):(c=r.setAttribute)==null||c.call(r,"theme",e),(d=r.refreshTheme)==null||d.call(r)})}static setTheme(e,t=null){if(h._cleanupGlobalAuto(),e==="auto")h._setupGlobalAuto(),h._applyGlobalTheme(Z("auto"),t,!0);else{let i=typeof e=="string"?_(e):e;t&&(i=J(i,t)),h.currentTheme=i,h.injectStyles(!0);let o=i.name||e;o&&h._updateThemeAttrs(o)}}static _applyGlobalTheme(e,t=null,i=!1){let o=_(e);t&&(o=J(o,t)),h.currentTheme=o,h.injectStyles(!0),h._updateThemeAttrs(e,i)}static _setupGlobalAuto(){var e;!window.matchMedia||h._globalAutoMq||(h._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),h._globalAutoListener=t=>{h._applyGlobalTheme(t.matches?"cave":"solar",null,!0)},(e=h._globalAutoMq.addEventListener||h._globalAutoMq.addListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener))}static _cleanupGlobalAuto(){var e;h._globalAutoMq&&h._globalAutoListener&&((e=h._globalAutoMq.removeEventListener||h._globalAutoMq.removeListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener),h._globalAutoMq=null,h._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static initGlobalListeners(){h.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let i=t.closest(".overtype-wrapper"),o=i==null?void 0:i._instance;o&&(o.options.showStats&&o.statsBar&&o._updateStats(),clearTimeout(o._selectionTimeout),o._selectionTimeout=setTimeout(()=>{o.updatePreview()},50))}}),h.globalListenersInitialized=!0)}};E(h,"instances",new WeakMap),E(h,"stylesInjected",!1),E(h,"globalListenersInitialized",!1),E(h,"instanceCount",0),E(h,"_mq",null),E(h,"_mqListener",null),E(h,"_autoInstances",new Set),E(h,"_globalAutoMq",null),E(h,"_globalAutoListener",null);var P=h;P.MarkdownParser=S;P.ShortcutsManager=z;P.themes={solar:A,cave:_("cave")};P.getTheme=_;P.currentTheme=A;var Fe=P;var Re="overtype-webcomponent-container",ct="Start typing...",pt=["value","theme","toolbar","height","min-height","max-height","placeholder","font-size","line-height","padding","auto-resize","autofocus","show-stats","smart-lists","readonly"],G=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._editor=null,this._initialized=!1,this._pendingOptions={},this._styleVersion=0,this._baseStyleElement=null,this._selectionChangeHandler=null,this._isConnected=!1,this._handleChange=this._handleChange.bind(this),this._handleKeydown=this._handleKeydown.bind(this)}_decodeValue(e){return typeof e!="string"?"":e.replace(/\\r/g,"\r").replace(/\\n/g,` + `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,i=this.wrapper,o=window.getComputedStyle(e),r=parseFloat(o.paddingTop),s=parseFloat(o.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),i.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,h.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new h(e,t)}static initFromData(e,t={}){let i=document.querySelectorAll(e);return Array.from(i).map(o=>{let r={...t};for(let s of o.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=h._parseDataValue(s.value)}return new h(o,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||h.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let i=h.getInstance(t);i&&i.destroy()})}static injectStyles(e=!1){if(h.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let i=h.currentTheme||A,o=R({theme:i}),r=document.createElement("style");r.className="overtype-styles",r.textContent=o,document.head.appendChild(r),h.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let i=o=>{t?(o.setAttribute("data-theme","auto"),o.setAttribute("data-resolved-theme",e)):o.setAttribute("data-theme",e)};document.querySelectorAll(".overtype-container").forEach(i),document.querySelectorAll(".overtype-wrapper").forEach(o=>{var r;o.closest(".overtype-container")||i(o),(r=o._instance)==null||r.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(o=>{var r,s,a;(r=o.setAttribute)==null||r.call(o,"theme",t?"auto":e),t&&((s=o.setAttribute)==null||s.call(o,"data-resolved-theme",e)),(a=o.refreshTheme)==null||a.call(o)})}static setTheme(e,t=null){if(h._cleanupGlobalAuto(),e==="auto")h._setupGlobalAuto(),h._applyGlobalTheme(Z("auto"),t,!0);else{let i=typeof e=="string"?_(e):e;t&&(i=J(i,t)),h.currentTheme=i,h.injectStyles(!0);let o=i.name||e;o&&h._updateThemeAttrs(o)}}static _applyGlobalTheme(e,t=null,i=!1){let o=_(e);t&&(o=J(o,t)),h.currentTheme=o,h.injectStyles(!0),h._updateThemeAttrs(e,i)}static _setupGlobalAuto(){var e;!window.matchMedia||h._globalAutoMq||(h._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),h._globalAutoListener=t=>{h._applyGlobalTheme(t.matches?"cave":"solar",null,!0)},(e=h._globalAutoMq.addEventListener||h._globalAutoMq.addListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener))}static _cleanupGlobalAuto(){var e;h._globalAutoMq&&h._globalAutoListener&&((e=h._globalAutoMq.removeEventListener||h._globalAutoMq.removeListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener),h._globalAutoMq=null,h._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let i=t._instance;i&&i.updatePreview&&i.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let i=t.getEditor();i&&i.updatePreview&&i.updatePreview()}})}static initGlobalListeners(){h.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),i=t==null?void 0:t._instance;i&&i.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let i=t.closest(".overtype-wrapper"),o=i==null?void 0:i._instance;o&&(o.options.showStats&&o.statsBar&&o._updateStats(),clearTimeout(o._selectionTimeout),o._selectionTimeout=setTimeout(()=>{o.updatePreview()},50))}}),h.globalListenersInitialized=!0)}};E(h,"instances",new WeakMap),E(h,"stylesInjected",!1),E(h,"globalListenersInitialized",!1),E(h,"instanceCount",0),E(h,"_mq",null),E(h,"_mqListener",null),E(h,"_autoInstances",new Set),E(h,"_globalAutoMq",null),E(h,"_globalAutoListener",null);var P=h;P.MarkdownParser=S;P.ShortcutsManager=z;P.themes={solar:A,cave:_("cave")};P.getTheme=_;P.currentTheme=A;var Fe=P;var Re="overtype-webcomponent-container",ct="Start typing...",pt=["value","theme","toolbar","height","min-height","max-height","placeholder","font-size","line-height","padding","auto-resize","autofocus","show-stats","smart-lists","readonly"],G=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._editor=null,this._initialized=!1,this._pendingOptions={},this._styleVersion=0,this._baseStyleElement=null,this._selectionChangeHandler=null,this._isConnected=!1,this._handleChange=this._handleChange.bind(this),this._handleKeydown=this._handleKeydown.bind(this)}_decodeValue(e){return typeof e!="string"?"":e.replace(/\\r/g,"\r").replace(/\\n/g,` `).replace(/\\t/g," ")}static get observedAttributes(){return pt}connectedCallback(){this._isConnected=!0,this._initializeEditor()}disconnectedCallback(){this._isConnected=!1,this._cleanup()}attributeChangedCallback(e,t,i){if(t!==i&&!this._silentUpdate){if(!this._initialized){this._pendingOptions[e]=i;return}this._updateOption(e,i)}}_initializeEditor(){if(!(this._initialized||!this._isConnected))try{let e=document.createElement("div");e.className=Re;let t=this.getAttribute("height"),i=this.getAttribute("min-height"),o=this.getAttribute("max-height");t&&(e.style.height=t),i&&(e.style.minHeight=i),o&&(e.style.maxHeight=o),this._injectStyles(),this.shadowRoot.appendChild(e);let r=this._getOptionsFromAttributes(),s=new Fe(e,r);this._editor=s[0],this._initialized=!0,this._editor&&this._editor.textarea&&(this._editor.textarea.addEventListener("scroll",()=>{this._editor&&this._editor.preview&&this._editor.textarea&&(this._editor.preview.scrollTop=this._editor.textarea.scrollTop,this._editor.preview.scrollLeft=this._editor.textarea.scrollLeft)}),this._editor.textarea.addEventListener("input",a=>{this._editor&&this._editor.handleInput&&this._editor.handleInput(a)}),this._editor.textarea.addEventListener("keydown",a=>{this._editor&&this._editor.handleKeydown&&this._editor.handleKeydown(a)}),this._selectionChangeHandler=()=>{if(document.activeElement===this){let a=this.shadowRoot.activeElement;a&&a===this._editor.textarea&&(this._editor.options.showStats&&this._editor.statsBar&&this._editor._updateStats(),this._editor.linkTooltip&&this._editor.linkTooltip.checkCursorPosition&&this._editor.linkTooltip.checkCursorPosition())}},document.addEventListener("selectionchange",this._selectionChangeHandler)),this._applyPendingOptions(),this._dispatchEvent("ready",{editor:this._editor})}catch(e){let t=e&&e.message?e.message:String(e);console.warn("OverType Web Component initialization failed:",t),this._dispatchEvent("error",{error:{message:t}})}}_injectStyles(){let e=document.createElement("style"),t=this.getAttribute("theme")||"solar",i=_(t),o=this._getOptionsFromAttributes(),r=R({...o,theme:i}),s=` /* Web Component Host Styles */ :host { diff --git a/dist/overtype.cjs b/dist/overtype.cjs index 8e06b05..13dd0ac 100644 --- a/dist/overtype.cjs +++ b/dist/overtype.cjs @@ -4428,37 +4428,27 @@ var _OverType = class _OverType { * @private */ static _updateThemeAttrs(themeName, isAuto = false) { - const containers = document.querySelectorAll(".overtype-container"); - const wrappers = document.querySelectorAll(".overtype-wrapper"); - containers.forEach((el) => { + const setTheme = (el) => { if (isAuto) { el.setAttribute("data-theme", "auto"); el.setAttribute("data-resolved-theme", themeName); } else { el.setAttribute("data-theme", themeName); } - }); - wrappers.forEach((wrapper) => { + }; + document.querySelectorAll(".overtype-container").forEach(setTheme); + document.querySelectorAll(".overtype-wrapper").forEach((w) => { var _a; - if (!wrapper.closest(".overtype-container")) { - if (isAuto) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } else { - wrapper.setAttribute("data-theme", themeName); - } - } - (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + if (!w.closest(".overtype-container")) + setTheme(w); + (_a = w._instance) == null ? void 0 : _a.updatePreview(); }); document.querySelectorAll("overtype-editor").forEach((wc) => { - var _a, _b, _c, _d; - if (isAuto) { - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + var _a, _b, _c; + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); - } else { - (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); - } - (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); }); } /** diff --git a/dist/overtype.esm.js b/dist/overtype.esm.js index 1107637..1aeb788 100644 --- a/dist/overtype.esm.js +++ b/dist/overtype.esm.js @@ -4402,37 +4402,27 @@ var _OverType = class _OverType { * @private */ static _updateThemeAttrs(themeName, isAuto = false) { - const containers = document.querySelectorAll(".overtype-container"); - const wrappers = document.querySelectorAll(".overtype-wrapper"); - containers.forEach((el) => { + const setTheme = (el) => { if (isAuto) { el.setAttribute("data-theme", "auto"); el.setAttribute("data-resolved-theme", themeName); } else { el.setAttribute("data-theme", themeName); } - }); - wrappers.forEach((wrapper) => { + }; + document.querySelectorAll(".overtype-container").forEach(setTheme); + document.querySelectorAll(".overtype-wrapper").forEach((w) => { var _a; - if (!wrapper.closest(".overtype-container")) { - if (isAuto) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } else { - wrapper.setAttribute("data-theme", themeName); - } - } - (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + if (!w.closest(".overtype-container")) + setTheme(w); + (_a = w._instance) == null ? void 0 : _a.updatePreview(); }); document.querySelectorAll("overtype-editor").forEach((wc) => { - var _a, _b, _c, _d; - if (isAuto) { - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + var _a, _b, _c; + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); - } else { - (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); - } - (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); }); } /** diff --git a/dist/overtype.esm.js.map b/dist/overtype.esm.js.map index e12ecfc..fc48e04 100644 --- a/dist/overtype.esm.js.map +++ b/dist/overtype.esm.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js", "../src/overtype.js"], - "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `[${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n // Single query for containers and wrappers\n const containers = document.querySelectorAll('.overtype-container');\n const wrappers = document.querySelectorAll('.overtype-wrapper');\n \n containers.forEach(el => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n });\n \n wrappers.forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n if (isAuto) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n } else {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n wrapper._instance?.updatePreview();\n });\n \n // Update web components\n document.querySelectorAll('overtype-editor').forEach(wc => {\n if (isAuto) {\n wc.setAttribute?.('theme', 'auto');\n wc.setAttribute?.('data-resolved-theme', themeName);\n } else {\n wc.setAttribute?.('theme', themeName);\n }\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], - "mappings": "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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;;;;;;;;;;;;;AC92BO,IAAM,UAAU;EACrB,MAAM;IACJ,QAAQ;IACR,QAAQ;IACR,WAAW;EACb;EACA,QAAQ;IACN,QAAQ;IACR,QAAQ;IACR,WAAW;EACb;EACA,MAAM;IACJ,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,aAAa;EACf;EACA,MAAM;IACJ,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,SAAS;EACX;EACA,YAAY;IACV,QAAQ;IACR,WAAW;IACX,eAAe;EACjB;EACA,cAAc;IACZ,QAAQ;IACR,WAAW;IACX,aAAa;EACf;EACA,OAAO;IACL,QAAQ;IACR,WAAW;IACX,sBAAsB;EACxB;EACA,UAAU;IACR,QAAQ;IACR,WAAW;IACX,sBAAsB;EACxB;EACA,SAAS,EAAE,QAAQ,KAAK;EACxB,SAAS,EAAE,QAAQ,MAAM;EACzB,SAAS,EAAE,QAAQ,OAAO;EAC1B,SAAS,EAAE,QAAQ,QAAQ;EAC3B,SAAS,EAAE,QAAQ,SAAS;EAC5B,SAAS,EAAE,QAAQ,UAAU;AAC/B;AAKO,SAAS,kBAAkB;AAChC,SAAO;IACL,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,aAAa;IACb,WAAW;IACX,aAAa;IACb,aAAa;IACb,SAAS;IACT,sBAAsB;IACtB,aAAa;IACb,eAAe;IACf,WAAW;EACb;AACF;AAKO,SAAS,kBAAkB,QAAQ;AACxC,SAAO,eAAA,eAAA,CAAA,GAAK,gBAAgB,CAAA,GAAM,MAAA;AACpC;AC1EA,IAAI,YAAY;AAcT,SAAS,eAAe;AAC7B,SAAO;AACT;AAEO,SAAS,SAAS,UAAU,SAAS,MAAM;AAEhD,MAAI,CAAC;AAAW;AAEhB,UAAQ,MAAM,aAAM,QAAQ,EAAE;AAC9B,UAAQ,IAAI,OAAO;AACnB,MAAI,MAAM;AACR,YAAQ,IAAI,SAAS,IAAI;EAC3B;AACA,UAAQ,SAAS;AACnB;AAEO,SAAS,eAAe,UAAU,OAAO;AAE9C,MAAI,CAAC;AAAW;AAEhB,QAAM,WAAW,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACpF,UAAQ,MAAM,wBAAiB,KAAK,EAAE;AACtC,UAAQ,IAAI,aAAa,GAAG,SAAS,cAAc,IAAI,SAAS,YAAY,EAAE;AAC9E,UAAQ,IAAI,kBAAkB,KAAK,UAAU,QAAQ,CAAC;AACtD,UAAQ,IAAI,WAAW,SAAS,MAAM;AAGtC,QAAM,SAAS,SAAS,MAAM,MAAM,KAAK,IAAI,GAAG,SAAS,iBAAiB,EAAE,GAAG,SAAS,cAAc;AACtG,QAAM,QAAQ,SAAS,MAAM,MAAM,SAAS,cAAc,KAAK,IAAI,SAAS,MAAM,QAAQ,SAAS,eAAe,EAAE,CAAC;AACrH,UAAQ,IAAI,YAAY,KAAK,UAAU,MAAM,IAAI,gBAAgB,KAAK,UAAU,KAAK,CAAC;AACtF,UAAQ,SAAS;AACnB;AAEO,SAAS,YAAY,QAAQ;AAElC,MAAI,CAAC;AAAW;AAEhB,UAAQ,MAAM,kBAAW;AACzB,UAAQ,IAAI,mBAAmB,KAAK,UAAU,OAAO,IAAI,CAAC;AAC1D,UAAQ,IAAI,kBAAkB,GAAG,OAAO,cAAc,IAAI,OAAO,YAAY,EAAE;AAC/E,UAAQ,SAAS;AACnB;ACtDA,IAAI,gBAAgB;AAUb,SAAS,WAAW,UAAU,EAAE,MAAM,gBAAgB,aAAa,GAAG;AAC3E,QAAMC,aAAY,aAAa;AAE/B,MAAIA,YAAW;AACb,YAAQ,MAAM,sBAAe;AAC7B,YAAQ,IAAI,sBAAsB,GAAG,SAAS,cAAc,IAAI,SAAS,YAAY,EAAE;AACvF,YAAQ,IAAI,mBAAmB,KAAK,UAAU,IAAI,CAAC;AACnD,YAAQ,IAAI,yBAAyB,gBAAgB,KAAK,YAAY;EACxE;AAGA,WAAS,MAAM;AAEf,QAAM,yBAAyB,SAAS;AACxC,QAAM,uBAAuB,SAAS;AACtC,QAAM,SAAS,SAAS,MAAM,MAAM,GAAG,sBAAsB;AAC7D,QAAM,QAAQ,SAAS,MAAM,MAAM,oBAAoB;AAEvD,MAAIA,YAAW;AACb,YAAQ,IAAI,0BAA0B,KAAK,UAAU,OAAO,MAAM,GAAG,CAAC,CAAC;AACvE,YAAQ,IAAI,0BAA0B,KAAK,UAAU,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;AACxE,YAAQ,IAAI,iCAAiC,KAAK,UAAU,SAAS,MAAM,MAAM,wBAAwB,oBAAoB,CAAC,CAAC;EACjI;AAGA,QAAM,gBAAgB,SAAS;AAI/B,QAAM,eAAe,2BAA2B;AAEhD,MAAI,kBAAkB,QAAQ,kBAAkB,MAAM;AACpD,aAAS,kBAAkB;AAC3B,QAAI;AACF,sBAAgB,SAAS,YAAY,cAAc,OAAO,IAAI;AAC9D,UAAIA;AAAW,gBAAQ,IAAI,yBAAyB,eAAe,iBAAiB,KAAK,MAAM,IAAI,EAAE,QAAQ,OAAO;IACtH,SAAS,OAAO;AACd,sBAAgB;AAChB,UAAIA;AAAW,gBAAQ,IAAI,4BAA4B,KAAK;IAC9D;AACA,aAAS,kBAAkB;EAC7B;AAEA,MAAIA,YAAW;AACb,YAAQ,IAAI,yBAAyB,aAAa;AAClD,YAAQ,IAAI,uBAAuB,aAAa;EAClD;AAGA,MAAI,eAAe;AACjB,UAAM,gBAAgB,SAAS,OAAO;AACtC,UAAM,cAAc,SAAS;AAE7B,QAAIA,YAAW;AACb,cAAQ,IAAI,oBAAoB,cAAc,MAAM;AACpD,cAAQ,IAAI,kBAAkB,YAAY,MAAM;IAClD;AAEA,QAAI,gBAAgB,eAAe;AACjC,UAAIA,YAAW;AACb,gBAAQ,IAAI,mDAAmD;AAC/D,gBAAQ,IAAI,aAAa,KAAK,UAAU,cAAc,MAAM,GAAG,GAAG,CAAC,CAAC;AACpE,gBAAQ,IAAI,WAAW,KAAK,UAAU,YAAY,MAAM,GAAG,GAAG,CAAC,CAAC;MAClE;IAGF;EACF;AAEA,MAAI,CAAC,eAAe;AAClB,QAAIA;AAAW,cAAQ,IAAI,wBAAwB;AAEnD,QAAI,SAAS,UAAU,eAAe;AACpC,UAAIA;AAAW,gBAAQ,IAAI,2CAA2C;AACtE,UAAI;AACF,iBAAS,YAAY,kBAAkB;MACzC,SAAS,GAAG;MAEZ;AACA,eAAS,QAAQ,SAAS,OAAO;AACjC,UAAI;AACF,iBAAS,YAAY,gBAAgB;MACvC,SAAS,GAAG;MAEZ;AACA,eAAS,cAAc,IAAI,YAAY,SAAS,EAAE,SAAS,MAAM,YAAY,KAAK,CAAC,CAAC;IACtF,OAAO;AACL,UAAIA;AAAW,gBAAQ,IAAI,6DAA6D;IAC1F;EACF;AAEA,MAAIA;AAAW,YAAQ,IAAI,4BAA4B,gBAAgB,YAAY;AACnF,MAAI,kBAAkB,QAAQ,gBAAgB,MAAM;AAClD,aAAS,kBAAkB,gBAAgB,YAAY;EACzD,OAAO;AACL,aAAS,kBAAkB,wBAAwB,SAAS,YAAY;EAC1E;AAEA,MAAIA,YAAW;AACb,YAAQ,IAAI,uBAAuB,SAAS,MAAM,MAAM;AACxD,YAAQ,SAAS;EACnB;AACF;AChHO,SAAS,gBAAgB,QAAQ;AACtC,SAAO,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,SAAS;AAC5C;AAKO,SAAS,mBAAmB,MAAM,GAAG;AAC1C,MAAI,QAAQ;AACZ,SAAO,KAAK,KAAK,KAAK,KAAK,QAAQ,CAAC,KAAK,QAAQ,CAAC,KAAK,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG;AAC7E;EACF;AACA,SAAO;AACT;AAKO,SAAS,iBAAiB,MAAM,GAAG,WAAW;AACnD,MAAI,QAAQ;AACZ,QAAM,aAAa,YAAY,OAAO;AACtC,SAAO,KAAK,KAAK,KAAK,CAAC,KAAK,KAAK,EAAE,MAAM,UAAU,GAAG;AACpD;EACF;AACA,SAAO;AACT;AAKO,SAAS,sBAAsB,UAAU;AAC9C,QAAM,QAAQ,SAAS,MAAM,MAAM,IAAI;AACvC,MAAI,UAAU;AACd,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS;AACjD,UAAM,aAAa,MAAM,KAAK,EAAE,SAAS;AACzC,QAAI,SAAS,kBAAkB,WAAW,SAAS,iBAAiB,UAAU,YAAY;AACxF,eAAS,iBAAiB;IAC5B;AACA,QAAI,SAAS,gBAAgB,WAAW,SAAS,eAAe,UAAU,YAAY;AAEpF,UAAI,UAAU,MAAM,SAAS,GAAG;AAC9B,iBAAS,eAAe,KAAK,IAAI,UAAU,MAAM,KAAK,EAAE,QAAQ,SAAS,MAAM,MAAM;MACvF,OAAO;AACL,iBAAS,eAAe,UAAU,aAAa;MACjD;IACF;AACA,eAAW;EACb;AACF;AAKO,SAAS,mBAAmB,UAAU,aAAa,aAAa,YAAY,OAAO;AACxF,MAAI,SAAS,mBAAmB,SAAS,cAAc;AACrD,aAAS,iBAAiB,mBAAmB,SAAS,OAAO,SAAS,cAAc;AACpF,aAAS,eAAe,iBAAiB,SAAS,OAAO,SAAS,cAAc,SAAS;EAC3F,OAAO;AACL,UAAM,yBAAyB,SAAS,iBAAiB,YAAY;AACrE,UAAM,uBAAuB,SAAS,eAAe,YAAY;AACjE,UAAM,mBAAmB,SAAS,MAAM,MAAM,wBAAwB,SAAS,cAAc,MAAM;AACnG,UAAM,iBAAiB,SAAS,MAAM,MAAM,SAAS,cAAc,oBAAoB,MAAM;AAC7F,QAAI,oBAAoB,gBAAgB;AACtC,eAAS,iBAAiB;AAC1B,eAAS,eAAe;IAC1B;EACF;AACA,SAAO,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AAC5E;AAKO,SAAS,+BAA+B,UAAU;AACvD,QAAM,kBAAkB,SAAS,MAAM,MAAM,GAAG,SAAS,cAAc;AACvE,QAAM,iBAAiB,SAAS,MAAM,MAAM,SAAS,YAAY;AAEjE,QAAM,eAAe,gBAAgB,MAAM,MAAM;AACjD,QAAM,cAAc,eAAe,MAAM,MAAM;AAC/C,QAAM,0BAA0B,eAAe,aAAa,CAAC,EAAE,SAAS;AACxE,QAAM,yBAAyB,cAAc,YAAY,CAAC,EAAE,SAAS;AAErE,MAAI,mBAAmB;AACvB,MAAI,oBAAoB;AAExB,MAAI,gBAAgB,MAAM,IAAI,KAAK,0BAA0B,GAAG;AAC9D,uBAAmB,KAAK,OAAO,IAAI,uBAAuB;EAC5D;AAEA,MAAI,eAAe,MAAM,IAAI,KAAK,yBAAyB,GAAG;AAC5D,wBAAoB,KAAK,OAAO,IAAI,sBAAsB;EAC5D;AAEA,SAAO,EAAE,kBAAkB,kBAAkB;AAC/C;AA2BO,SAAS,mBAAmB,UAAU,WAAW,UAAU,CAAC,GAAG;AAEpE,QAAM,gBAAgB,SAAS;AAC/B,QAAM,cAAc,SAAS;AAC7B,QAAM,qBAAqB,kBAAkB;AAG7C,QAAM,QAAQ,SAAS;AACvB,MAAI,YAAY;AAGhB,SAAO,YAAY,KAAK,MAAM,YAAY,CAAC,MAAM,MAAM;AACrD;EACF;AAGA,MAAI,oBAAoB;AAEtB,QAAI,UAAU;AAGd,WAAO,UAAU,MAAM,UAAU,MAAM,OAAO,MAAM,MAAM;AACxD;IACF;AAEA,aAAS,iBAAiB;AAC1B,aAAS,eAAe;EAC1B,OAAO;AAEL,0BAAsB,QAAQ;EAChC;AAGA,QAAM,SAAS,UAAU,QAAQ;AAGjC,MAAI,QAAQ,iBAAiB;AAE3B,UAAM,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACxF,UAAM,aAAa,aAAa,WAAW,QAAQ,MAAM;AACzD,UAAM,WAAW,QAAQ,gBAAgB,YAAY,eAAe,aAAa,SAAS;AAC1F,WAAO,iBAAiB,SAAS;AACjC,WAAO,eAAe,SAAS;EACjC,WAAW,QAAQ,QAAQ;AAEzB,UAAM,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACxF,UAAM,aAAa,aAAa,WAAW,QAAQ,MAAM;AAEzD,QAAI,oBAAoB;AAEtB,UAAI,YAAY;AAEd,eAAO,iBAAiB,KAAK,IAAI,gBAAgB,QAAQ,OAAO,QAAQ,SAAS;AACjF,eAAO,eAAe,OAAO;MAC/B,OAAO;AAEL,eAAO,iBAAiB,gBAAgB,QAAQ,OAAO;AACvD,eAAO,eAAe,OAAO;MAC/B;IACF,OAAO;AAEL,UAAI,YAAY;AAEd,eAAO,iBAAiB,KAAK,IAAI,gBAAgB,QAAQ,OAAO,QAAQ,SAAS;AACjF,eAAO,eAAe,KAAK,IAAI,cAAc,QAAQ,OAAO,QAAQ,SAAS;MAC/E,OAAO;AAEL,eAAO,iBAAiB,gBAAgB,QAAQ,OAAO;AACvD,eAAO,eAAe,cAAc,QAAQ,OAAO;MACrD;IACF;EACF;AAEA,SAAO;AACT;AC/LO,SAAS,WAAW,UAAU,OAAO;AAC1C,MAAI;AACJ,MAAI;AAEJ,QAAM,EAAE,QAAQ,QAAQ,aAAa,aAAa,aAAa,aAAa,SAAS,sBAAsB,UAAU,IAAI;AACzH,QAAM,yBAAyB,SAAS;AACxC,QAAM,uBAAuB,SAAS;AAEtC,MAAI,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACtF,MAAI,cAAc,gBAAgB,YAAY,KAAK,eAAe,YAAY,SAAS,IAAI,GAAG,WAAW;IAAO;AAChH,MAAI,cAAc,gBAAgB,YAAY,KAAK,eAAe,YAAY,SAAS,IAAI;EAAK,WAAW,KAAK;AAEhH,MAAI,aAAa;AACf,UAAM,kBAAkB,SAAS,MAAM,SAAS,iBAAiB,CAAC;AAClE,QAAI,SAAS,mBAAmB,KAAK,mBAAmB,QAAQ,CAAC,gBAAgB,MAAM,IAAI,GAAG;AAC5F,oBAAc,IAAI,WAAW;IAC/B;EACF;AAEA,iBAAe,mBAAmB,UAAU,aAAa,aAAa,MAAM,SAAS;AACrF,MAAI,iBAAiB,SAAS;AAC9B,MAAI,eAAe,SAAS;AAC5B,QAAM,iBAAiB,eAAe,YAAY,SAAS,KAAK,YAAY,QAAQ,WAAW,IAAI,MAAM,aAAa,SAAS;AAE/H,MAAI,sBAAsB;AACxB,UAAM,MAAM,+BAA+B,QAAQ;AACnD,uBAAmB,IAAI;AACvB,wBAAoB,IAAI;AACxB,kBAAc,mBAAmB;AACjC,mBAAe;EACjB;AAGA,MAAI,aAAa,WAAW,WAAW,KAAK,aAAa,SAAS,WAAW,GAAG;AAC9E,UAAM,kBAAkB,aAAa,MAAM,YAAY,QAAQ,aAAa,SAAS,YAAY,MAAM;AACvG,QAAI,2BAA2B,sBAAsB;AACnD,UAAI,WAAW,yBAAyB,YAAY;AACpD,iBAAW,KAAK,IAAI,UAAU,cAAc;AAC5C,iBAAW,KAAK,IAAI,UAAU,iBAAiB,gBAAgB,MAAM;AACrE,uBAAiB,eAAe;IAClC,OAAO;AACL,qBAAe,iBAAiB,gBAAgB;IAClD;AACA,WAAO,EAAE,MAAM,iBAAiB,gBAAgB,aAAa;EAC/D,WAAW,CAAC,gBAAgB;AAE1B,QAAI,kBAAkB,cAAc,eAAe;AACnD,qBAAiB,yBAAyB,YAAY;AACtD,mBAAe,uBAAuB,YAAY;AAClD,UAAM,kBAAkB,aAAa,MAAM,YAAY;AACvD,QAAI,aAAa,iBAAiB;AAChC,YAAM,oBAAoB,gBAAgB,CAAC,KAAK;AAChD,YAAM,qBAAqB,gBAAgB,CAAC,KAAK;AACjD,wBAAkB,oBAAoB,cAAc,aAAa,KAAK,IAAI,cAAc;AACxF,wBAAkB,kBAAkB;AACpC,sBAAgB,mBAAmB;IACrC;AACA,WAAO,EAAE,MAAM,iBAAiB,gBAAgB,aAAa;EAC/D,WAAW,WAAW,QAAQ,SAAS,KAAK,aAAa,MAAM,OAAO,GAAG;AAEvE,kBAAc,YAAY,QAAQ,aAAa,YAAY;AAC3D,UAAM,kBAAkB,cAAc;AACtC,qBAAiB,eAAe,iBAAiB,YAAY;AAC7D,WAAO,EAAE,MAAM,iBAAiB,gBAAgB,aAAa;EAC/D,OAAO;AAEL,UAAM,kBAAkB,cAAc,eAAe;AACrD,qBAAiB,iBAAiB,YAAY,SAAS,aAAa,SAAS,YAAY,QAAQ,WAAW;AAC5G,mBAAe,iBAAiB,YAAY;AAC5C,WAAO,EAAE,MAAM,iBAAiB,gBAAgB,aAAa;EAC/D;AACF;AAyBO,SAAS,eAAe,UAAU,OAAO;AAC9C,QAAM,EAAE,QAAQ,QAAQ,qBAAqB,IAAI;AACjD,MAAI,OAAO,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AAC9E,MAAI,iBAAiB,SAAS;AAC9B,MAAI,eAAe,SAAS;AAC5B,QAAM,QAAQ,KAAK,MAAM,IAAI;AAG7B,QAAM,YAAY,MAAM,MAAM,CAAA,SAAQ,KAAK,WAAW,MAAM,MAAM,CAAC,UAAU,KAAK,SAAS,MAAM,EAAE;AAEnG,MAAI,WAAW;AAEb,WAAO,MAAM,IAAI,CAAA,SAAQ;AACvB,UAAI,SAAS,KAAK,MAAM,OAAO,MAAM;AACrC,UAAI,QAAQ;AACV,iBAAS,OAAO,MAAM,GAAG,OAAO,SAAS,OAAO,MAAM;MACxD;AACA,aAAO;IACT,CAAC,EAAE,KAAK,IAAI;AACZ,mBAAe,iBAAiB,KAAK;EACvC,OAAO;AAEL,WAAO,MAAM,IAAI,CAAA,SAAQ,SAAS,QAAQ,UAAU,GAAG,EAAE,KAAK,IAAI;AAClE,QAAI,sBAAsB;AACxB,YAAM,EAAE,kBAAkB,kBAAkB,IAAI,+BAA+B,QAAQ;AACvF,wBAAkB,iBAAiB;AACnC,qBAAe,iBAAiB,KAAK;AACrC,aAAO,mBAAmB,OAAO;IACnC;EACF;AAEA,SAAO,EAAE,MAAM,gBAAgB,aAAa;AAC9C;ACjIA,SAAS,qBAAqB,MAAM;AAClC,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,mBAAmB;AACzB,QAAM,wBAAwB,MAAM,MAAM,CAAA,SAAQ,iBAAiB,KAAK,IAAI,CAAC;AAC7E,MAAI,SAAS;AACb,MAAI,uBAAuB;AACzB,aAAS,MAAM,IAAI,CAAA,SAAQ,KAAK,QAAQ,kBAAkB,EAAE,CAAC;EAC/D;AAEA,SAAO;IACL,MAAM,OAAO,KAAK,IAAI;IACtB,WAAW;EACb;AACF;AAKA,SAAS,uBAAuB,MAAM;AACpC,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,sBAAsB;AAC5B,QAAM,0BAA0B,MAAM,MAAM,CAAA,SAAQ,KAAK,WAAW,mBAAmB,CAAC;AACxF,MAAI,SAAS;AACb,MAAI,yBAAyB;AAC3B,aAAS,MAAM,IAAI,CAAA,SAAQ,KAAK,MAAM,oBAAoB,MAAM,CAAC;EACnE;AAEA,SAAO;IACL,MAAM,OAAO,KAAK,IAAI;IACtB,WAAW;EACb;AACF;AAKA,SAAS,WAAW,OAAO,eAAe;AACxC,MAAI,eAAe;AACjB,WAAO;EACT,OAAO;AACL,WAAO,GAAG,QAAQ,CAAC;EACrB;AACF;AAKA,SAAS,uBAAuB,OAAO,cAAc;AACnD,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,MAAM,aAAa;AACrB,iBAAa,qBAAqB,YAAY;AAC9C,6BAAyB,uBAAuB,WAAW,IAAI;AAC/D,mBAAe,uBAAuB;EACxC,OAAO;AACL,iBAAa,uBAAuB,YAAY;AAChD,6BAAyB,qBAAqB,WAAW,IAAI;AAC7D,mBAAe,uBAAuB;EACxC;AAEA,SAAO,CAAC,YAAY,wBAAwB,YAAY;AAC1D;AAKO,SAAS,UAAU,UAAU,OAAO;AACzC,QAAM,qBAAqB,SAAS,mBAAmB,SAAS;AAChE,MAAI,iBAAiB,SAAS;AAC9B,MAAI,eAAe,SAAS;AAG5B,wBAAsB,QAAQ;AAE9B,QAAM,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AAGxF,QAAM,CAAC,YAAY,wBAAwB,YAAY,IAAI,uBAAuB,OAAO,YAAY;AAErG,QAAM,gBAAgB,aAAa,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU;AACnE,WAAO,GAAG,WAAW,OAAO,MAAM,aAAa,CAAC,GAAG,KAAK;EAC1D,CAAC;AAED,QAAM,oBAAoB,cAAc,OAAO,CAAC,eAAe,eAAe,iBAAiB;AAC7F,WAAO,gBAAgB,WAAW,cAAc,MAAM,aAAa,EAAE;EACvE,GAAG,CAAC;AAEJ,QAAM,gCAAgC,cAAc,OAAO,CAAC,eAAe,eAAe,iBAAiB;AACzG,WAAO,gBAAgB,WAAW,cAAc,CAAC,MAAM,aAAa,EAAE;EACxE,GAAG,CAAC;AAGJ,MAAI,WAAW,WAAW;AACxB,QAAI,oBAAoB;AACtB,uBAAiB,KAAK,IAAI,iBAAiB,WAAW,GAAG,MAAM,aAAa,EAAE,QAAQ,CAAC;AACvF,qBAAe;IACjB,OAAO;AACL,uBAAiB,SAAS;AAC1B,qBAAe,SAAS,eAAe;IACzC;AACA,WAAO,EAAE,MAAM,cAAc,gBAAgB,aAAa;EAC5D;AAGA,QAAM,EAAE,kBAAkB,kBAAkB,IAAI,+BAA+B,QAAQ;AACvF,QAAM,OAAO,mBAAmB,cAAc,KAAK,IAAI,IAAI;AAE3D,MAAI,oBAAoB;AACtB,qBAAiB,KAAK,IAAI,iBAAiB,WAAW,GAAG,MAAM,aAAa,EAAE,SAAS,iBAAiB,QAAQ,CAAC;AACjH,mBAAe;EACjB,OAAO;AACL,QAAI,uBAAuB,WAAW;AAEpC,uBAAiB,KAAK,IAAI,SAAS,iBAAiB,iBAAiB,QAAQ,CAAC;AAC9E,qBAAe,SAAS,eAAe,iBAAiB,SAAS,oBAAoB;IACvF,OAAO;AAEL,uBAAiB,KAAK,IAAI,SAAS,iBAAiB,iBAAiB,QAAQ,CAAC;AAC9E,qBAAe,SAAS,eAAe,iBAAiB,SAAS;IACnE;EACF;AAEA,SAAO,EAAE,MAAM,gBAAgB,aAAa;AAC9C;AAKO,SAAS,eAAe,UAAU,OAAO;AAE9C,QAAM,SAAS;IACb;IACA,CAAC,OAAO,UAAU,IAAI,KAAK;IAC3B;;MAEE,iBAAiB,CAAC,YAAY,UAAU,QAAQ,cAAc;AAE5D,cAAM,cAAc,SAAS,MAAM,MAAM,WAAW,SAAS,YAAY;AACzE,cAAM,mBAAmB;AACzB,cAAM,qBAAqB;AAG3B,cAAM,iBAAiB,iBAAiB,KAAK,WAAW;AACxD,cAAM,mBAAmB,mBAAmB,KAAK,WAAW;AAC5D,cAAM,oBAAqB,MAAM,eAAe,kBAAoB,MAAM,iBAAiB;AAE3F,YAAI,aAAa,QAAQ;AAEvB,cAAI,mBAAmB;AAErB,kBAAM,cAAc,YAAY,MAAM,MAAM,cAAc,mBAAmB,kBAAkB;AAC/F,kBAAM,eAAe,cAAc,YAAY,CAAC,EAAE,SAAS;AAC3D,mBAAO;cACL,OAAO,KAAK,IAAI,WAAW,cAAc,SAAS;cAClD,KAAK,KAAK,IAAI,WAAW,cAAc,SAAS;YAClD;UACF,WAAW,kBAAkB,kBAAkB;AAE7C,kBAAM,iBAAiB,YAAY,MAAM,iBAAiB,mBAAmB,kBAAkB;AAC/F,kBAAM,kBAAkB,iBAAiB,eAAe,CAAC,EAAE,SAAS;AACpE,kBAAM,kBAAkB,MAAM,gBAAgB,IAAI;AAClD,kBAAM,aAAa,kBAAkB;AACrC,mBAAO;cACL,OAAO,WAAW;cAClB,KAAK,WAAW;YAClB;UACF,OAAO;AAEL,kBAAM,eAAe,MAAM,gBAAgB,IAAI;AAC/C,mBAAO;cACL,OAAO,WAAW;cAClB,KAAK,WAAW;YAClB;UACF;QACF,OAAO;AAEL,cAAI,mBAAmB;AAErB,kBAAM,cAAc,YAAY,MAAM,MAAM,cAAc,mBAAmB,kBAAkB;AAC/F,kBAAM,eAAe,cAAc,YAAY,CAAC,EAAE,SAAS;AAC3D,mBAAO;cACL,OAAO,KAAK,IAAI,WAAW,cAAc,SAAS;cAClD,KAAK,KAAK,IAAI,SAAS,cAAc,SAAS;YAChD;UACF,WAAW,kBAAkB,kBAAkB;AAE7C,kBAAM,iBAAiB,YAAY,MAAM,iBAAiB,mBAAmB,kBAAkB;AAC/F,kBAAM,kBAAkB,iBAAiB,eAAe,CAAC,EAAE,SAAS;AACpE,kBAAM,kBAAkB,MAAM,gBAAgB,IAAI;AAClD,kBAAM,aAAa,kBAAkB;AACrC,mBAAO;cACL,OAAO,WAAW;cAClB,KAAK,SAAS;YAChB;UACF,OAAO;AAEL,kBAAM,eAAe,MAAM,gBAAgB,IAAI;AAC/C,mBAAO;cACL,OAAO,WAAW;cAClB,KAAK,SAAS;YAChB;UACF;QACF;MACF;IACF;EACF;AAEA,aAAW,UAAU,MAAM;AAC7B;ACtMO,SAAS,iBAAiB,UAAU;AACzC,MAAI,CAAC;AAAU,WAAO,CAAC;AAEvB,QAAM,UAAU,CAAC;AACjB,QAAM,EAAE,gBAAgB,cAAc,MAAM,IAAI;AAGhD,QAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,MAAI,YAAY;AAChB,MAAI,cAAc;AAElB,aAAW,QAAQ,OAAO;AACxB,QAAI,kBAAkB,aAAa,kBAAkB,YAAY,KAAK,QAAQ;AAC5E,oBAAc;AACd;IACF;AACA,iBAAa,KAAK,SAAS;EAC7B;AAGA,MAAI,YAAY,WAAW,IAAI,GAAG;AAChC,QAAI,YAAY,WAAW,QAAQ,KAAK,YAAY,WAAW,QAAQ,GAAG;AACxE,cAAQ,KAAK,WAAW;IAC1B,OAAO;AACL,cAAQ,KAAK,aAAa;IAC5B;EACF;AAEA,MAAI,WAAW,KAAK,WAAW,GAAG;AAChC,YAAQ,KAAK,eAAe;EAC9B;AAEA,MAAI,YAAY,WAAW,IAAI,GAAG;AAChC,YAAQ,KAAK,OAAO;EACtB;AAEA,MAAI,YAAY,WAAW,IAAI;AAAG,YAAQ,KAAK,QAAQ;AACvD,MAAI,YAAY,WAAW,KAAK;AAAG,YAAQ,KAAK,UAAU;AAC1D,MAAI,YAAY,WAAW,MAAM;AAAG,YAAQ,KAAK,UAAU;AAG3D,QAAM,aAAa,KAAK,IAAI,GAAG,iBAAiB,EAAE;AAClD,QAAM,YAAY,KAAK,IAAI,MAAM,QAAQ,eAAe,EAAE;AAC1D,QAAM,cAAc,MAAM,MAAM,YAAY,SAAS;AAGrD,MAAI,YAAY,SAAS,IAAI,GAAG;AAC9B,UAAM,eAAe,MAAM,MAAM,KAAK,IAAI,GAAG,iBAAiB,GAAG,GAAG,cAAc;AAClF,UAAM,cAAc,MAAM,MAAM,cAAc,KAAK,IAAI,MAAM,QAAQ,eAAe,GAAG,CAAC;AACxF,UAAM,eAAe,aAAa,YAAY,IAAI;AAClD,UAAM,gBAAgB,YAAY,QAAQ,IAAI;AAC9C,QAAI,iBAAiB,MAAM,kBAAkB,IAAI;AAC/C,cAAQ,KAAK,MAAM;IACrB;EACF;AAGA,MAAI,YAAY,SAAS,GAAG,GAAG;AAC7B,UAAM,eAAe,MAAM,MAAM,KAAK,IAAI,GAAG,iBAAiB,GAAG,GAAG,cAAc;AAClF,UAAM,cAAc,MAAM,MAAM,cAAc,KAAK,IAAI,MAAM,QAAQ,eAAe,GAAG,CAAC;AACxF,UAAM,iBAAiB,aAAa,YAAY,GAAG;AACnD,UAAM,kBAAkB,YAAY,QAAQ,GAAG;AAC/C,QAAI,mBAAmB,MAAM,oBAAoB,IAAI;AACnD,cAAQ,KAAK,QAAQ;IACvB;EACF;AAGA,MAAI,YAAY,SAAS,GAAG,GAAG;AAC7B,UAAM,eAAe,MAAM,MAAM,KAAK,IAAI,GAAG,iBAAiB,GAAG,GAAG,cAAc;AAClF,UAAM,cAAc,MAAM,MAAM,cAAc,KAAK,IAAI,MAAM,QAAQ,eAAe,GAAG,CAAC;AACxF,QAAI,aAAa,SAAS,GAAG,KAAK,YAAY,SAAS,GAAG,GAAG;AAC3D,cAAQ,KAAK,MAAM;IACrB;EACF;AAGA,MAAI,YAAY,SAAS,GAAG,KAAK,YAAY,SAAS,GAAG,GAAG;AAC1D,UAAM,eAAe,MAAM,MAAM,KAAK,IAAI,GAAG,iBAAiB,GAAG,GAAG,cAAc;AAClF,UAAM,cAAc,MAAM,MAAM,cAAc,KAAK,IAAI,MAAM,QAAQ,eAAe,GAAG,CAAC;AACxF,UAAM,kBAAkB,aAAa,YAAY,GAAG;AACpD,UAAM,mBAAmB,YAAY,QAAQ,GAAG;AAChD,QAAI,oBAAoB,MAAM,qBAAqB,IAAI;AACrD,YAAM,eAAe,MAAM,MAAM,eAAe,mBAAmB,GAAG,eAAe,mBAAmB,EAAE;AAC1G,UAAI,aAAa,WAAW,GAAG,GAAG;AAChC,gBAAQ,KAAK,MAAM;MACrB;IACF;EACF;AAEA,SAAO;AACT;ACjGO,SAAS,WAAW,UAAU;AACnC,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAEzD,WAAS,cAAc,UAAU;AACjC,iBAAe,UAAU,QAAQ;AAEjC,QAAM,QAAQ,kBAAkB,QAAQ,IAAI;AAC5C,QAAM,SAAS,WAAW,UAAU,KAAK;AAEzC,cAAY,MAAM;AAElB,aAAW,UAAU,MAAM;AAE3B,iBAAe,UAAU,OAAO;AAClC;AAKO,SAAS,aAAa,UAAU;AACrC,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AACzD,QAAM,QAAQ,kBAAkB,QAAQ,MAAM;AAC9C,QAAM,SAAS,WAAW,UAAU,KAAK;AACzC,aAAW,UAAU,MAAM;AAC7B;AAKO,SAAS,WAAW,UAAU;AACnC,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAGzD,QAAM,QAAQ,kBAAkB,QAAQ,IAAI;AAC5C,QAAM,SAAS,WAAW,UAAU,KAAK;AACzC,aAAW,UAAU,MAAM;AAC7B;AAKO,SAAS,WAAW,UAAU,UAAU,CAAC,GAAG;AACjD,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAEzD,QAAM,eAAe,SAAS,MAAM,MAAM,SAAS,gBAAgB,SAAS,YAAY;AACxF,MAAI,QAAQ,kBAAkB,QAAQ,IAAI;AAG1C,QAAM,QAAQ,gBAAgB,aAAa,MAAM,cAAc;AAE/D,MAAI,SAAS,CAAC,QAAQ,KAAK;AAEzB,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,cAAc;EAEtB,WAAW,QAAQ,KAAK;AAEtB,UAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,UAAM,cAAc;EACtB;AAGA,MAAI,QAAQ,QAAQ,CAAC,cAAc;AAEjC,UAAM,MAAM,SAAS;AACrB,aAAS,QAAQ,SAAS,MAAM,MAAM,GAAG,GAAG,IAAI,QAAQ,OAAO,SAAS,MAAM,MAAM,GAAG;AACvF,aAAS,iBAAiB;AAC1B,aAAS,eAAe,MAAM,QAAQ,KAAK;EAC7C;AAEA,QAAM,SAAS,WAAW,UAAU,KAAK;AACzC,aAAW,UAAU,MAAM;AAC7B;AAKO,SAAS,iBAAiB,UAAU;AACzC,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AACzD,QAAM,QAAQ,kBAAkB,QAAQ,UAAU;AAClD,iBAAe,UAAU,KAAK;AAChC;AAKO,SAAS,mBAAmB,UAAU;AAC3C,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AACzD,QAAM,QAAQ,kBAAkB,QAAQ,YAAY;AACpD,iBAAe,UAAU,KAAK;AAChC;AAMO,SAAS,YAAY,UAAU;AACpC,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAEzD,WAAS,eAAe,UAAU;AAClC,iBAAe,UAAU,SAAS;AAElC,QAAM,QAAQ,kBAAkB,QAAQ,KAAK;AAG7C,QAAM,SAAS;IACb;IACA,CAAC,OAAO,eAAe,IAAI,KAAK;IAChC,EAAE,QAAQ,MAAM,OAAO;EACzB;AAEA,cAAY,MAAM;AAClB,aAAW,UAAU,MAAM;AAC3B,iBAAe,UAAU,OAAO;AAClC;AAMO,SAAS,eAAe,UAAU;AACvC,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AAEzD,QAAM,QAAQ,kBAAkB,QAAQ,QAAQ;AAGhD,QAAM,SAAS;IACb;IACA,CAAC,OAAO,eAAe,IAAI,KAAK;IAChC,EAAE,QAAQ,MAAM,OAAO;EACzB;AAEA,aAAW,UAAU,MAAM;AAC7B;AAKO,SAAS,aAAa,UAAU,QAAQ,GAAG,SAAS,OAAO;AAChE,MAAI,CAAC,YAAY,SAAS,YAAY,SAAS;AAAU;AACzD,MAAI,QAAQ,KAAK,QAAQ;AAAG,YAAQ;AAEpC,WAAS,gBAAgB,iCAAiC;AAC1D,WAAS,gBAAgB,UAAU,KAAK,aAAa,MAAM,EAAE;AAC7D,WAAS,gBAAgB,mBAAmB,SAAS,cAAc,IAAI,SAAS,YAAY,EAAE;AAE9F,QAAM,YAAY,SAAS,UAAU,IAAI,MAAM,KAAK;AACpD,QAAM,QAAQ,kBAAkB,QAAQ,SAAS,KAAK,QAAQ,OAAO;AACrE,WAAS,gBAAgB,kBAAkB,MAAM,MAAM,GAAG;AAG1D,QAAM,QAAQ,SAAS;AACvB,QAAM,gBAAgB,SAAS;AAC/B,QAAM,cAAc,SAAS;AAG7B,MAAI,YAAY;AAChB,SAAO,YAAY,KAAK,MAAM,YAAY,CAAC,MAAM,MAAM;AACrD;EACF;AACA,MAAI,UAAU;AACd,SAAO,UAAU,MAAM,UAAU,MAAM,OAAO,MAAM,MAAM;AACxD;EACF;AAGA,QAAM,qBAAqB,MAAM,MAAM,WAAW,OAAO;AACzD,WAAS,gBAAgB,2BAA2B,kBAAkB,GAAG;AAEzE,QAAM,sBAAsB,mBAAmB,MAAM,cAAc;AACnE,QAAM,gBAAgB,sBAAsB,oBAAoB,CAAC,EAAE,SAAS;AAC5E,QAAM,uBAAuB,sBAAsB,oBAAoB,CAAC,EAAE,SAAS;AAEnF,WAAS,gBAAgB,wBAAwB;AACjD,WAAS,gBAAgB,cAAc,sBAAsB,IAAI,oBAAoB,CAAC,CAAC,MAAM,MAAM,EAAE;AACrG,WAAS,gBAAgB,uBAAuB,aAAa,EAAE;AAC/D,WAAS,gBAAgB,+BAA+B,oBAAoB,EAAE;AAC9E,WAAS,gBAAgB,qBAAqB,KAAK,EAAE;AAGrD,QAAM,kBAAkB,UAAU,kBAAkB;AACpD,WAAS,gBAAgB,sBAAsB,eAAe,YAAY,MAAM,mBAAmB,aAAa,WAAW,KAAK,GAAG;AAGnI,QAAM,SAAS;IACb;IACA,CAAC,OAAO;AACN,YAAM,cAAc,GAAG,MAAM,MAAM,GAAG,gBAAgB,GAAG,YAAY;AACrE,eAAS,gBAAgB,uBAAuB,WAAW,GAAG;AAG9D,YAAM,cAAc,YAAY,QAAQ,cAAc,EAAE;AACxD,eAAS,gBAAgB,kBAAkB,WAAW,GAAG;AAEzD,UAAI;AAEJ,UAAI,iBAAiB;AAEnB,iBAAS,gBAAgB,wCAAwC;AACjE,kBAAU;MACZ,WAAW,gBAAgB,GAAG;AAE5B,iBAAS,gBAAgB,sBAAsB,aAAa,UAAU,KAAK,EAAE;AAC7E,kBAAU,MAAM,SAAS;MAC3B,OAAO;AAEL,iBAAS,gBAAgB,2BAA2B;AACpD,kBAAU,MAAM,SAAS;MAC3B;AAEA,eAAS,gBAAgB,cAAc,OAAO,GAAG;AAEjD,aAAO;QACL,MAAM;QACN,gBAAgB,GAAG;QACnB,cAAc,GAAG;MACnB;IACF;IACA;MACE,QAAQ,MAAM;;MAEd,iBAAiB,CAAC,YAAY,UAAU,QAAQ,iBAAiB;AAC/D,iBAAS,gBAAgB,sBAAsB;AAC/C,iBAAS,gBAAgB,yBAAyB,UAAU,EAAE;AAC9D,iBAAS,gBAAgB,wBAAwB,eAAe,EAAE;AAClE,iBAAS,gBAAgB,iBAAiB,QAAQ,aAAa,MAAM,EAAE;AACvE,iBAAS,gBAAgB,qBAAqB,YAAY,EAAE;AAE5D,YAAI,iBAAiB;AAEnB,gBAAM,aAAa,KAAK,IAAI,WAAW,sBAAsB,YAAY;AACzE,mBAAS,gBAAgB,sCAAsC,oBAAoB,EAAE;AACrF,iBAAO;YACL,OAAO;YACP,KAAK,aAAa,SAAS,aAAa,KAAK,IAAI,SAAS,sBAAsB,YAAY;UAC9F;QACF,WAAW,uBAAuB,GAAG;AAEnC,gBAAM,aAAa,MAAM,OAAO,SAAS;AACzC,mBAAS,gBAAgB,sCAAsC,UAAU,EAAE;AAC3E,iBAAO;YACL,OAAO,WAAW;YAClB,KAAK,SAAS;UAChB;QACF,OAAO;AAEL,mBAAS,gBAAgB,oCAAoC,MAAM,OAAO,MAAM,EAAE;AAClF,iBAAO;YACL,OAAO,WAAW,MAAM,OAAO;YAC/B,KAAK,SAAS,MAAM,OAAO;UAC7B;QACF;MACF;IACF;EACF;AAEA,WAAS,gBAAgB,uBAAuB,OAAO,IAAI,aAAa,OAAO,cAAc,IAAI,OAAO,YAAY,EAAE;AACtH,WAAS,gBAAgB,+BAA+B;AAExD,aAAW,UAAU,MAAM;AAC7B;AAKO,SAAS,SAAS,UAAU;AACjC,eAAa,UAAU,GAAG,IAAI;AAChC;AAKO,SAAS,SAAS,UAAU;AACjC,eAAa,UAAU,GAAG,IAAI;AAChC;AAKO,SAAS,SAAS,UAAU;AACjC,eAAa,UAAU,GAAG,IAAI;AAChC;AAKO,SAASC,kBAAiB,UAAU;AACzC,SAAO,iBAAU,QAAQ;AAC3B;;;ACzSO,IAAM,UAAN,MAAc;AAAA,EACnB,YAAY,QAAQ,UAAU,CAAC,GAAG;AAChC,SAAK,SAAS;AACd,SAAK,YAAY;AACjB,SAAK,UAAU,CAAC;AAGhB,SAAK,iBAAiB,QAAQ,kBAAkB,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS;AACP,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,YAAY;AAC3B,SAAK,UAAU,aAAa,QAAQ,SAAS;AAC7C,SAAK,UAAU,aAAa,cAAc,oBAAoB;AAG9D,SAAK,eAAe,QAAQ,kBAAgB;AAC1C,UAAI,aAAa,SAAS,aAAa;AACrC,cAAM,YAAY,KAAK,gBAAgB;AACvC,aAAK,UAAU,YAAY,SAAS;AAAA,MACtC,OAAO;AACL,cAAM,SAAS,KAAK,aAAa,YAAY;AAC7C,aAAK,QAAQ,aAAa,IAAI,IAAI;AAClC,aAAK,UAAU,YAAY,MAAM;AAAA,MACnC;AAAA,IACF,CAAC;AAGD,SAAK,OAAO,UAAU,aAAa,KAAK,WAAW,KAAK,OAAO,OAAO;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB;AAChB,UAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,cAAU,YAAY;AACtB,cAAU,aAAa,QAAQ,WAAW;AAC1C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,cAAc;AACzB,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,YAAY;AACnB,WAAO,OAAO;AACd,WAAO,aAAa,eAAe,aAAa,IAAI;AACpD,WAAO,QAAQ,aAAa,SAAS;AACrC,WAAO,aAAa,cAAc,aAAa,SAAS,aAAa,IAAI;AACzE,WAAO,YAAY,KAAK,YAAY,aAAa,QAAQ,EAAE;AAG3D,QAAI,aAAa,SAAS,YAAY;AACpC,aAAO,UAAU,IAAI,cAAc;AACnC,aAAO,QAAQ,WAAW;AAC1B,aAAO,iBAAiB,SAAS,CAAC,MAAM;AACtC,UAAE,eAAe;AACjB,aAAK,uBAAuB,MAAM;AAAA,MACpC,CAAC;AACD,aAAO;AAAA,IACT;AAGA,WAAO,gBAAgB,CAAC,MAAM;AAC5B,QAAE,eAAe;AACjB,YAAM,WAAW,aAAa,YAAY,aAAa;AACvD,WAAK,OAAO,cAAc,UAAU,CAAC;AAAA,IACvC;AAEA,WAAO,iBAAiB,SAAS,OAAO,aAAa;AACrD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,kBAAkB;AAEnC,QAAI,oBAAoB,OAAO,qBAAqB,YAAY,OAAO,iBAAiB,WAAW,YAAY;AAC7G,WAAK,OAAO,SAAS,MAAM;AAC3B,UAAI;AACF,cAAM,iBAAiB,OAAO;AAAA,UAC5B,QAAQ,KAAK;AAAA,UACb,UAAU,MAAM,KAAK,OAAO,SAAS;AAAA,UACrC,UAAU,CAAC,UAAU,KAAK,OAAO,SAAS,KAAK;AAAA,UAC/C,OAAO;AAAA,QACT,CAAC;AACD,eAAO;AAAA,MACT,SAAS,OAAO;AACd,gBAAQ,MAAM,WAAW,iBAAiB,IAAI,YAAY,KAAK;AAC/D,aAAK,OAAO,QAAQ,cAAc,IAAI,YAAY,gBAAgB;AAAA,UAChE,QAAQ,EAAE,YAAY,iBAAiB,MAAM,MAAM;AAAA,QACrD,CAAC,CAAC;AACF,eAAO;AAAA,MACT;AAAA,IACF;AAGA,QAAI,OAAO,qBAAqB,UAAU;AACxC,aAAO,KAAK,OAAO,cAAc,kBAAkB,IAAI;AAAA,IACzD;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,KAAK;AACf,QAAI,OAAO,QAAQ;AAAU,aAAO;AAGpC,UAAM,UAAU,IACb,QAAQ,uDAAuD,EAAE,EACjE,QAAQ,kCAAkC,EAAE,EAC5C,QAAQ,2BAA2B,EAAE;AAExC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAuB,QAAQ;AAE7B,UAAM,mBAAmB,SAAS,cAAc,yBAAyB;AACzE,QAAI,kBAAkB;AACpB,uBAAiB,OAAO;AACxB,aAAO,UAAU,OAAO,iBAAiB;AACzC;AAAA,IACF;AAEA,WAAO,UAAU,IAAI,iBAAiB;AAEtC,UAAM,WAAW,KAAK,uBAAuB,MAAM;AAGnD,UAAM,OAAO,OAAO,sBAAsB;AAC1C,aAAS,MAAM,WAAW;AAC1B,aAAS,MAAM,MAAM,GAAG,KAAK,SAAS,CAAC;AACvC,aAAS,MAAM,OAAO,GAAG,KAAK,IAAI;AAElC,aAAS,KAAK,YAAY,QAAQ;AAGlC,SAAK,sBAAsB,CAAC,MAAM;AAChC,UAAI,CAAC,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC,OAAO,SAAS,EAAE,MAAM,GAAG;AAC9D,iBAAS,OAAO;AAChB,eAAO,UAAU,OAAO,iBAAiB;AACzC,iBAAS,oBAAoB,SAAS,KAAK,mBAAmB;AAAA,MAChE;AAAA,IACF;AAEA,eAAW,MAAM;AACf,eAAS,iBAAiB,SAAS,KAAK,mBAAmB;AAAA,IAC7D,GAAG,CAAC;AAAA,EACN;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,QAAQ;AAC7B,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,aAAS,YAAY;AAErB,UAAM,QAAQ;AAAA,MACZ,EAAE,IAAI,UAAU,OAAO,eAAe,MAAM,SAAI;AAAA,MAChD,EAAE,IAAI,SAAS,OAAO,kBAAkB,MAAM,SAAI;AAAA,MAClD,EAAE,IAAI,WAAW,OAAO,gBAAgB,MAAM,SAAI;AAAA,IACpD;AAEA,UAAM,cAAc,KAAK,OAAO,UAAU,QAAQ,QAAQ;AAE1D,UAAM,QAAQ,UAAQ;AACpB,YAAM,WAAW,SAAS,cAAc,QAAQ;AAChD,eAAS,YAAY;AACrB,eAAS,OAAO;AAChB,eAAS,cAAc,KAAK;AAE5B,UAAI,KAAK,OAAO,aAAa;AAC3B,iBAAS,UAAU,IAAI,QAAQ;AAC/B,iBAAS,aAAa,gBAAgB,MAAM;AAC5C,cAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,kBAAU,YAAY;AACtB,kBAAU,cAAc,KAAK;AAC7B,iBAAS,QAAQ,SAAS;AAAA,MAC5B;AAEA,eAAS,iBAAiB,SAAS,CAAC,MAAM;AACxC,UAAE,eAAe;AAGjB,gBAAO,KAAK,IAAI;AAAA,UACd,KAAK;AACH,iBAAK,OAAO,kBAAkB;AAC9B;AAAA,UACF,KAAK;AACH,iBAAK,OAAO,gBAAgB;AAC5B;AAAA,UACF,KAAK;AAAA,UACL;AACE,iBAAK,OAAO,mBAAmB;AAC/B;AAAA,QACJ;AAEA,iBAAS,OAAO;AAChB,eAAO,UAAU,OAAO,iBAAiB;AACzC,iBAAS,oBAAoB,SAAS,KAAK,mBAAmB;AAAA,MAChE,CAAC;AAED,eAAS,YAAY,QAAQ;AAAA,IAC/B,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB;AA5OvB;AA6OI,QAAI;AACF,YAAM,kBAAgB,KAAgB,sBAAhB;AAAA,QACpB,KAAK,OAAO;AAAA,QACZ,KAAK,OAAO,SAAS;AAAA,YAClB,CAAC;AAEN,aAAO,QAAQ,KAAK,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM,MAAM,MAAM;AACvD,YAAI,SAAS;AAAY;AAEzB,YAAI,WAAW;AAEf,gBAAO,MAAM;AAAA,UACX,KAAK;AACH,uBAAW,cAAc,SAAS,MAAM;AACxC;AAAA,UACF,KAAK;AACH,uBAAW,cAAc,SAAS,QAAQ;AAC1C;AAAA,UACF,KAAK;AACH,uBAAW;AACX;AAAA,UACF,KAAK;AACH,uBAAW,cAAc,SAAS,aAAa;AAC/C;AAAA,UACF,KAAK;AACH,uBAAW,cAAc,SAAS,eAAe;AACjD;AAAA,UACF,KAAK;AACH,uBAAW,cAAc,SAAS,WAAW;AAC7C;AAAA,UACF,KAAK;AACH,uBAAW,cAAc,SAAS,OAAO;AACzC;AAAA,UACF,KAAK;AACH,uBAAW,cAAc,SAAS,QAAQ;AAC1C;AAAA,UACF,KAAK;AACH,uBAAW,cAAc,SAAS,UAAU;AAC5C;AAAA,UACF,KAAK;AACH,uBAAW,cAAc,SAAS,UAAU;AAC5C;AAAA,QACJ;AAEA,eAAO,UAAU,OAAO,UAAU,QAAQ;AAC1C,eAAO,aAAa,gBAAgB,SAAS,SAAS,CAAC;AAAA,MACzD,CAAC;AAAA,IACH,SAAS,OAAO;AAAA,IAEhB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AACR,QAAI,KAAK,WAAW;AAElB,UAAI,KAAK,qBAAqB;AAC5B,iBAAS,oBAAoB,SAAS,KAAK,mBAAmB;AAAA,MAChE;AAGA,aAAO,OAAO,KAAK,OAAO,EAAE,QAAQ,YAAU;AAC5C,YAAI,OAAO,eAAe;AACxB,iBAAO,oBAAoB,SAAS,OAAO,aAAa;AACxD,iBAAO,OAAO;AAAA,QAChB;AAAA,MACF,CAAC;AAGD,WAAK,UAAU,OAAO;AACtB,WAAK,YAAY;AACjB,WAAK,UAAU,CAAC;AAAA,IAClB;AAAA,EACF;AACF;;;ACnTO,IAAM,cAAN,MAAkB;AAAA,EACvB,YAAY,QAAQ;AAClB,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,0BAA0B;AAC/B,SAAK,gBAAgB;AACrB,SAAK,aAAa;AAClB,SAAK,mBAAmB;AAExB,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,MAAM,OAAO;AAEX,UAAM,4BAA4B,IAAI,SAAS,sBAAsB,KACnC,IAAI,SAAS,uBAAuB;AAGtE,QAAI,CAAC,2BAA2B;AAC9B,UAAI;AAEF,cAAM,WAAW,IAAI,SAAS,OAAO,oBAAoB;AACzD,cAAM,EAAE,iBAAiB,QAAQ,OAAO,KAAK,IAAI,MAAM;AAAA,UACrD;AAAA,QACF;AACA,aAAK,aAAa,EAAE,iBAAiB,QAAQ,OAAO,KAAK;AACzD,aAAK,gBAAgB;AAAA,MACvB,SAAS,OAAO;AAEd,gBAAQ,KAAK,wCAAwC,KAAK;AAC1D,aAAK,aAAa;AAClB,aAAK,gBAAgB;AAAA,MACvB;AAAA,IACF;AAIA,SAAK,cAAc;AAGnB,SAAK,OAAO,SAAS,iBAAiB,mBAAmB,MAAM,KAAK,oBAAoB,CAAC;AACzF,SAAK,OAAO,SAAS,iBAAiB,SAAS,OAAK;AAClD,UAAI,EAAE,IAAI,SAAS,OAAO,KAAK,EAAE,QAAQ,UAAU,EAAE,QAAQ,OAAO;AAClE,aAAK,oBAAoB;AAAA,MAC3B;AAAA,IACF,CAAC;AAGD,SAAK,OAAO,SAAS,iBAAiB,SAAS,MAAM,KAAK,KAAK,CAAC;AAGhE,SAAK,OAAO,SAAS,iBAAiB,UAAU,MAAM;AACpD,UAAI,KAAK,iBAAiB,KAAK,aAAa;AAE1C,aAAK,mBAAmB,KAAK,WAAW;AAAA,MAC1C,OAAO;AAEL,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,CAAC;AAGD,SAAK,OAAO,SAAS,iBAAiB,QAAQ,MAAM;AAClD,UAAI,CAAC,KAAK,kBAAkB;AAC1B,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,CAAC;AAGD,SAAK,0BAA0B,MAAM;AACnC,UAAI,SAAS,QAAQ;AACnB,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AACA,aAAS,iBAAiB,oBAAoB,KAAK,uBAAuB;AAG1E,SAAK,QAAQ,iBAAiB,cAAc,MAAM;AAChD,WAAK,mBAAmB;AACxB,WAAK,WAAW;AAAA,IAClB,CAAC;AACD,SAAK,QAAQ,iBAAiB,cAAc,MAAM;AAChD,WAAK,mBAAmB;AACxB,WAAK,aAAa;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,gBAAgB;AAGd,SAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,SAAK,QAAQ,YAAY;AAGzB,SAAK,QAAQ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWzB,SAAK,QAAQ,iBAAiB,SAAS,OAAK;AAC1C,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,UAAI,KAAK,aAAa;AACpB,eAAO,KAAK,KAAK,YAAY,KAAK,QAAQ;AAC1C,aAAK,KAAK;AAAA,MACZ;AAAA,IACF,CAAC;AAGD,SAAK,OAAO,UAAU,YAAY,KAAK,OAAO;AAAA,EAChD;AAAA,EAEA,sBAAsB;AACpB,UAAM,YAAY,KAAK,OAAO,SAAS;AACvC,UAAM,OAAO,KAAK,OAAO,SAAS;AAGlC,UAAM,WAAW,KAAK,mBAAmB,MAAM,SAAS;AAExD,QAAI,UAAU;AACZ,UAAI,CAAC,KAAK,eAAe,KAAK,YAAY,QAAQ,SAAS,OAAO,KAAK,YAAY,UAAU,SAAS,OAAO;AAC3G,aAAK,KAAK,QAAQ;AAAA,MACpB;AAAA,IACF,OAAO;AACL,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,mBAAmB,MAAM,UAAU;AAEjC,UAAM,YAAY;AAClB,QAAI;AACJ,QAAI,YAAY;AAEhB,YAAQ,QAAQ,UAAU,KAAK,IAAI,OAAO,MAAM;AAC9C,YAAM,QAAQ,MAAM;AACpB,YAAM,MAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAEnC,UAAI,YAAY,SAAS,YAAY,KAAK;AACxC,eAAO;AAAA,UACL,MAAM,MAAM,CAAC;AAAA,UACb,KAAK,MAAM,CAAC;AAAA,UACZ,OAAO;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,UAAU;AACb,SAAK,cAAc;AACnB,SAAK,WAAW;AAGhB,UAAM,UAAU,KAAK,QAAQ,cAAc,4BAA4B;AACvE,YAAQ,cAAc,SAAS;AAE/B,QAAI,KAAK,eAAe;AACtB,WAAK,mBAAmB,QAAQ;AAAA,IAClC,OAAO;AACL,WAAK,0BAA0B,QAAQ;AAAA,IACzC;AAEA,SAAK,QAAQ,UAAU,IAAI,SAAS;AAAA,EACtC;AAAA,EAEA,0BAA0B,UAAU;AAElC,SAAK,QAAQ,MAAM,YAAY,mBAAmB,UAAU,SAAS,KAAK,EAAE;AAAA,EAC9E;AAAA,EAEA,MAAM,mBAAmB,UAAU;AAEjC,UAAM,gBAAgB,KAAK,kBAAkB,SAAS,KAAK;AAE3D,QAAI,CAAC,eAAe;AAClB;AAAA,IACF;AAGA,UAAM,OAAO,cAAc,sBAAsB;AACjD,QAAI,KAAK,UAAU,KAAK,KAAK,WAAW,GAAG;AACzC;AAAA,IACF;AAEA,QAAI;AAEF,YAAM,EAAE,GAAG,EAAE,IAAI,MAAM,KAAK,WAAW;AAAA,QACrC;AAAA,QACA,KAAK;AAAA,QACL;AAAA,UACE,WAAW;AAAA,UACX,YAAY;AAAA,YACV,KAAK,WAAW,OAAO,CAAC;AAAA,YACxB,KAAK,WAAW,MAAM,EAAE,SAAS,EAAE,CAAC;AAAA,YACpC,KAAK,WAAW,KAAK;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAGA,aAAO,OAAO,KAAK,QAAQ,OAAO;AAAA,QAChC,MAAM,GAAG,CAAC;AAAA,QACV,KAAK,GAAG,CAAC;AAAA,QACT,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,SAAS,OAAO;AAEd,cAAQ,KAAK,mCAAmC,KAAK;AACrD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,kBAAkB,WAAW;AAE3B,UAAM,UAAU,KAAK,OAAO;AAE5B,WAAO,QAAQ,cAAc,oBAAoB,SAAS,IAAI;AAAA,EAChE;AAAA,EAEA,OAAO;AACL,SAAK,QAAQ,UAAU,OAAO,SAAS;AACvC,SAAK,cAAc;AACnB,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,eAAe;AACb,SAAK,WAAW;AAChB,SAAK,cAAc,WAAW,MAAM,KAAK,KAAK,GAAG,GAAG;AAAA,EACtD;AAAA,EAEA,aAAa;AACX,QAAI,KAAK,aAAa;AACpB,mBAAa,KAAK,WAAW;AAC7B,WAAK,cAAc;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,UAAU;AACR,SAAK,WAAW;AAGhB,QAAI,KAAK,yBAAyB;AAChC,eAAS,oBAAoB,oBAAoB,KAAK,uBAAuB;AAC7E,WAAK,0BAA0B;AAAA,IACjC;AAEA,QAAI,KAAK,WAAW,KAAK,QAAQ,YAAY;AAC3C,WAAK,QAAQ,WAAW,YAAY,KAAK,OAAO;AAAA,IAClD;AACA,SAAK,UAAU;AACf,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,gBAAgB;AACrB,SAAK,mBAAmB;AAAA,EAC1B;AACF;;;AC7QO,IAAM,WAAW;AAAA;AAAA;AAAA;AAKjB,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAMnB,IAAM,SAAS;AAAA;AAAA;AAIf,IAAM,SAAS;AAAA;AAAA;AAIf,IAAM,SAAS;AAAA;AAAA;AAIf,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAMjB,IAAM,WAAW;AAAA;AAAA;AAAA;AAAA;AAOjB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASvB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUxB,IAAM,YAAY;AAAA;AAAA;AAAA;AAKlB,IAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASrB,IAAM,UAAU;AAAA;AAAA;AAAA;;;AC3DhB,IAAM,iBAAiB;AAAA,EAC5B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,WAAW,OAAO,QAAQ;AAC1C,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,aAAa,OAAO,QAAQ;AAC5C,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,WAAW,OAAO,QAAQ;AAC1C,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,WAAW;AAAA,IACT,MAAM;AAAA;AAAA,EAER;AAAA,EAEA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,WAAW,OAAO,QAAQ;AAC1C,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,SAAS,OAAO,QAAQ;AACxC,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,SAAS,OAAO,QAAQ;AACxC,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,IAAI;AAAA,IACF,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,SAAS,OAAO,QAAQ;AACxC,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,YAAY;AAAA,IACV,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,iBAAiB,OAAO,QAAQ;AAChD,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,aAAa;AAAA,IACX,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,mBAAmB,OAAO,QAAQ;AAClD,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,UAAoB,gBAAgB;AAClC,QAAgB,eAAe,OAAO,QAAQ;AAC9C,eAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,MAAY;AAAA,IACZ,OAAO;AAAA,IACP,QAAQ,CAAC,EAAE,OAAO,MAAM;AACtB,MAAgB,YAAY,OAAO,QAAQ;AAC3C,aAAO,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR,MAAM;AAAA,IACN,MAAY;AAAA,IACZ,OAAO;AAAA;AAAA;AAAA,EAGT;AACF;AAMO,IAAM,wBAAwB;AAAA,EACnC,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AACjB;;;AC5JA,SAAS,gBAAgB,SAAS;AAChC,QAAM,MAAM,CAAC;AACb,GAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,QAAQ;AAC/B,QAAI,CAAC,OAAO,IAAI,SAAS;AAAa;AACtC,UAAM,KAAK,IAAI,YAAY,IAAI;AAC/B,QAAI,IAAI,QAAQ;AACd,UAAI,EAAE,IAAI,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAOA,SAAS,iBAAiB,SAAS;AACjC,QAAM,OAAO,WAAW;AACxB,MAAI,CAAC,MAAM,QAAQ,IAAI;AAAG,WAAO;AACjC,SAAO,KAAK,IAAI,CAAC,SAAS;AAAA,IACxB,OAAM,2BAAK,SAAQ;AAAA,IACnB,WAAU,2BAAK,cAAY,2BAAK,SAAQ;AAAA,IACxC,OAAM,2BAAK,SAAQ;AAAA,IACnB,QAAO,2BAAK,UAAS;AAAA,EACvB,EAAE;AACJ;AAQA,SAAS,sBAAsB,aAAa,aAAa;AACvD,QAAM,OAAO,iBAAiB,WAAW;AACzC,QAAM,OAAO,iBAAiB,WAAW;AAEzC,MAAI,SAAS,QAAQ,SAAS;AAAM,WAAO,SAAS;AACpD,MAAI,KAAK,WAAW,KAAK;AAAQ,WAAO;AAExC,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,EAAE,SAAS,EAAE,QACb,EAAE,aAAa,EAAE,YACjB,EAAE,SAAS,EAAE,QACb,EAAE,UAAU,EAAE,OAAO;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAKA,IAAM,YAAN,MAAM,UAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBX,YAAY,QAAQ,UAAU,CAAC,GAAG;AAEhC,QAAI;AAEJ,QAAI,OAAO,WAAW,UAAU;AAC9B,iBAAW,SAAS,iBAAiB,MAAM;AAC3C,UAAI,SAAS,WAAW,GAAG;AACzB,cAAM,IAAI,MAAM,mCAAmC,MAAM,EAAE;AAAA,MAC7D;AACA,iBAAW,MAAM,KAAK,QAAQ;AAAA,IAChC,WAAW,kBAAkB,SAAS;AACpC,iBAAW,CAAC,MAAM;AAAA,IACpB,WAAW,kBAAkB,UAAU;AACrC,iBAAW,MAAM,KAAK,MAAM;AAAA,IAC9B,WAAW,MAAM,QAAQ,MAAM,GAAG;AAChC,iBAAW;AAAA,IACb,OAAO;AACL,YAAM,IAAI,MAAM,sEAAsE;AAAA,IACxF;AAGA,UAAM,YAAY,SAAS,IAAI,aAAW;AAExC,UAAI,QAAQ,kBAAkB;AAE5B,gBAAQ,iBAAiB,OAAO,OAAO;AACvC,eAAO,QAAQ;AAAA,MACjB;AAGA,YAAM,WAAW,OAAO,OAAO,UAAS,SAAS;AACjD,eAAS,MAAM,SAAS,OAAO;AAC/B,cAAQ,mBAAmB;AAC3B,gBAAS,UAAU,IAAI,SAAS,QAAQ;AACxC,aAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAS,UAAU,CAAC,GAAG;AAC3B,SAAK,UAAU;AAGf,SAAK,gBAAgB,QAAQ,SAAS;AAGtC,SAAK,sBAAsB;AAC3B,SAAK,oBAAoB;AAEzB,SAAK,UAAU,KAAK,cAAc,OAAO;AACzC,SAAK,aAAa,EAAE,UAAS;AAC7B,SAAK,cAAc;AAGnB,cAAS,aAAa;AAGtB,cAAS,oBAAoB;AAG7B,UAAM,YAAY,QAAQ,cAAc,qBAAqB;AAC7D,UAAM,UAAU,QAAQ,cAAc,mBAAmB;AACzD,QAAI,aAAa,SAAS;AACxB,WAAK,gBAAgB,WAAW,OAAO;AAAA,IACzC,OAAO;AACL,WAAK,kBAAkB;AAAA,IACzB;AAGA,QAAI,KAAK,eAAe;AACtB,WAAK,SAAS,KAAK,aAAa;AAAA,IAClC;AAGA,SAAK,YAAY,IAAI,iBAAiB,IAAI;AAG1C,SAAK,mBAAmB;AAGxB,SAAK,cAAc,IAAI,YAAY,IAAI;AAKvC,0BAAsB,MAAM;AAC1B,4BAAsB,MAAM;AAC1B,aAAK,SAAS,YAAY,KAAK,QAAQ;AACvC,aAAK,SAAS,aAAa,KAAK,QAAQ;AAAA,MAC1C,CAAC;AAAA,IACH,CAAC;AAGD,SAAK,cAAc;AAGnB,QAAI,KAAK,QAAQ,UAAU;AACzB,WAAK,QAAQ,SAAS,KAAK,SAAS,GAAG,IAAI;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,SAAS;AACrB,UAAM,WAAW;AAAA;AAAA,MAEf,UAAU;AAAA,MACV,YAAY;AAAA;AAAA,MAEZ,YAAY;AAAA,MACZ,SAAS;AAAA;AAAA,MAGT,QAAQ;AAAA,QACN,UAAU;AAAA;AAAA,QACV,SAAS;AAAA,QACT,YAAY;AAAA,MACd;AAAA;AAAA,MAGA,eAAe,CAAC;AAAA;AAAA,MAGhB,WAAW;AAAA,MACX,YAAY;AAAA;AAAA,MACZ,WAAW;AAAA;AAAA,MACX,WAAW;AAAA;AAAA,MACX,aAAa;AAAA,MACb,OAAO;AAAA;AAAA,MAGP,UAAU;AAAA,MACV,WAAW;AAAA;AAAA,MAGX,mBAAmB;AAAA,MACnB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,gBAAgB;AAAA;AAAA,MAChB,gBAAgB;AAAA,MAChB,YAAY;AAAA;AAAA,MACZ,iBAAiB;AAAA;AAAA,IACnB;AAGA,UAAM,EAAE,OAAO,QAAQ,GAAG,aAAa,IAAI;AAE3C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,WAAW,SAAS;AAElC,QAAI,aAAa,UAAU,UAAU,SAAS,oBAAoB,GAAG;AACnE,WAAK,YAAY;AACjB,WAAK,UAAU,UAAU,cAAc,mBAAmB;AAAA,IAC5D,WAAW,SAAS;AAElB,WAAK,UAAU;AAEf,WAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,WAAK,UAAU,YAAY;AAE3B,YAAM,aAAa,KAAK,iBAAiB,UAAS,gBAAgB;AAClE,YAAM,YAAY,OAAO,eAAe,WAAW,aAAa,WAAW;AAC3E,UAAI,WAAW;AACb,aAAK,UAAU,aAAa,cAAc,SAAS;AAAA,MACrD;AAGA,UAAI,KAAK,eAAe;AACtB,cAAM,WAAW,OAAO,KAAK,kBAAkB,WAAW,SAAS,KAAK,aAAa,IAAI,KAAK;AAC9F,YAAI,YAAY,SAAS,QAAQ;AAC/B,gBAAM,UAAU,eAAe,SAAS,MAAM;AAC9C,eAAK,UAAU,MAAM,WAAW;AAAA,QAClC;AAAA,MACF;AACA,cAAQ,WAAW,aAAa,KAAK,WAAW,OAAO;AACvD,WAAK,UAAU,YAAY,OAAO;AAAA,IACpC;AAEA,QAAI,CAAC,KAAK,SAAS;AAEjB,UAAI;AAAW,kBAAU,OAAO;AAChC,UAAI;AAAS,gBAAQ,OAAO;AAC5B,WAAK,kBAAkB;AACvB;AAAA,IACF;AAEA,SAAK,WAAW,KAAK,QAAQ,cAAc,iBAAiB;AAC5D,SAAK,UAAU,KAAK,QAAQ,cAAc,mBAAmB;AAE7D,QAAI,CAAC,KAAK,YAAY,CAAC,KAAK,SAAS;AAEnC,WAAK,UAAU,OAAO;AACtB,WAAK,kBAAkB;AACvB;AAAA,IACF;AAGA,SAAK,QAAQ,YAAY;AAGzB,QAAI,KAAK,QAAQ,UAAU;AACzB,WAAK,QAAQ,MAAM,YAAY,wBAAwB,KAAK,QAAQ,QAAQ;AAAA,IAC9E;AACA,QAAI,KAAK,QAAQ,YAAY;AAC3B,WAAK,QAAQ,MAAM,YAAY,0BAA0B,OAAO,KAAK,QAAQ,UAAU,CAAC;AAAA,IAC1F;AACA,QAAI,KAAK,QAAQ,SAAS;AACxB,WAAK,QAAQ,MAAM,YAAY,sBAAsB,KAAK,QAAQ,OAAO;AAAA,IAC3E;AAGA,SAAK,mBAAmB;AAGxB,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB;AAElB,UAAM,UAAU,KAAK,gBAAgB;AAGrC,SAAK,QAAQ,YAAY;AAGzB,SAAK,WAAW;AAGhB,QAAI,WAAW,KAAK,QAAQ,OAAO;AACjC,WAAK,SAAS,WAAW,KAAK,QAAQ,KAAK;AAAA,IAC7C;AAGA,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB;AAEhB,UAAM,WAAW,KAAK,QAAQ,cAAc,iBAAiB;AAC7D,QAAI;AAAU,aAAO,SAAS;AAG9B,WAAO,KAAK,QAAQ,eAAe;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AAEX,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,YAAY;AAG3B,UAAM,aAAa,KAAK,iBAAiB,UAAS,gBAAgB;AAClE,UAAM,YAAY,OAAO,eAAe,WAAW,aAAa,WAAW;AAC3E,QAAI,WAAW;AACb,WAAK,UAAU,aAAa,cAAc,SAAS;AAAA,IACrD;AAGA,QAAI,KAAK,eAAe;AACtB,YAAM,WAAW,OAAO,KAAK,kBAAkB,WAAW,SAAS,KAAK,aAAa,IAAI,KAAK;AAC9F,UAAI,YAAY,SAAS,QAAQ;AAC/B,cAAM,UAAU,eAAe,SAAS,MAAM;AAC9C,aAAK,UAAU,MAAM,WAAW;AAAA,MAClC;AAAA,IACF;AAGA,SAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,SAAK,QAAQ,YAAY;AAIzB,QAAI,KAAK,QAAQ,UAAU;AACzB,WAAK,QAAQ,MAAM,YAAY,wBAAwB,KAAK,QAAQ,QAAQ;AAAA,IAC9E;AACA,QAAI,KAAK,QAAQ,YAAY;AAC3B,WAAK,QAAQ,MAAM,YAAY,0BAA0B,OAAO,KAAK,QAAQ,UAAU,CAAC;AAAA,IAC1F;AACA,QAAI,KAAK,QAAQ,SAAS;AACxB,WAAK,QAAQ,MAAM,YAAY,sBAAsB,KAAK,QAAQ,OAAO;AAAA,IAC3E;AAEA,SAAK,QAAQ,YAAY;AAGzB,SAAK,WAAW,SAAS,cAAc,UAAU;AACjD,SAAK,SAAS,YAAY;AAC1B,SAAK,SAAS,cAAc,KAAK,QAAQ;AACzC,SAAK,mBAAmB;AAGxB,QAAI,KAAK,QAAQ,eAAe;AAC9B,aAAO,QAAQ,KAAK,QAAQ,aAAa,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACnE,YAAI,QAAQ,eAAe,QAAQ,SAAS;AAC1C,eAAK,SAAS,aAAa,MAAM;AAAA,QACnC,WAAW,QAAQ,WAAW,OAAO,UAAU,UAAU;AACvD,iBAAO,OAAO,KAAK,SAAS,OAAO,KAAK;AAAA,QAC1C,OAAO;AACL,eAAK,SAAS,aAAa,KAAK,KAAK;AAAA,QACvC;AAAA,MACF,CAAC;AAAA,IACH;AAGA,SAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,SAAK,QAAQ,YAAY;AACzB,SAAK,QAAQ,aAAa,eAAe,MAAM;AAG/C,SAAK,QAAQ,YAAY,KAAK,QAAQ;AACtC,SAAK,QAAQ,YAAY,KAAK,OAAO;AAKrC,SAAK,UAAU,YAAY,KAAK,OAAO;AAGvC,QAAI,KAAK,QAAQ,WAAW;AAC1B,WAAK,WAAW,SAAS,cAAc,KAAK;AAC5C,WAAK,SAAS,YAAY;AAC1B,WAAK,UAAU,YAAY,KAAK,QAAQ;AACxC,WAAK,aAAa;AAAA,IACpB;AAGA,SAAK,QAAQ,YAAY,KAAK,SAAS;AAGvC,QAAI,KAAK,QAAQ,YAAY;AAC3B,WAAK,iBAAiB;AAAA,IACxB,OAAO;AAEL,WAAK,UAAU,UAAU,OAAO,sBAAsB;AAAA,IACxD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB;AACnB,SAAK,SAAS,aAAa,gBAAgB,KAAK;AAChD,SAAK,SAAS,aAAa,eAAe,KAAK;AAC/C,SAAK,SAAS,aAAa,kBAAkB,KAAK;AAClD,SAAK,SAAS,aAAa,cAAc,OAAO;AAChD,SAAK,SAAS,aAAa,cAAc,OAAO;AAChD,SAAK,SAAS,aAAa,qBAAqB,OAAO;AACvD,SAAK,SAAS,aAAa,yBAAyB,OAAO;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB;AAEf,UAAMC,kBAAiB,KAAK,QAAQ,kBAAkB;AAEtD,SAAK,UAAU,IAAI,QAAQ,MAAM,EAAE,gBAAAA,gBAAe,CAAC;AACnD,SAAK,QAAQ,OAAO;AAGpB,SAAK,4BAA4B,MAAM;AACrC,UAAI,KAAK,SAAS;AAChB,aAAK,QAAQ,mBAAmB;AAAA,MAClC;AAAA,IACF;AACA,SAAK,wBAAwB,MAAM;AACjC,UAAI,KAAK,SAAS;AAChB,aAAK,QAAQ,mBAAmB;AAAA,MAClC;AAAA,IACF;AAGA,SAAK,SAAS,iBAAiB,mBAAmB,KAAK,yBAAyB;AAChF,SAAK,SAAS,iBAAiB,SAAS,KAAK,qBAAqB;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,2BAA2B;AACzB,QAAI,KAAK,2BAA2B;AAClC,WAAK,SAAS,oBAAoB,mBAAmB,KAAK,yBAAyB;AACnF,WAAK,4BAA4B;AAAA,IACnC;AACA,QAAI,KAAK,uBAAuB;AAC9B,WAAK,SAAS,oBAAoB,SAAS,KAAK,qBAAqB;AACrE,WAAK,wBAAwB;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,qBAAqB;AAEnB,SAAK,cAAc,gBAAgB,qBAAqB;AAGxD,QAAI,KAAK,QAAQ,gBAAgB;AAC/B,aAAO,OAAO,KAAK,aAAa,gBAAgB,KAAK,QAAQ,cAAc,CAAC;AAAA,IAC9E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB;AAEd,QAAI,KAAK,QAAQ,WAAW;AAC1B,WAAK,SAAS,MAAM;AAAA,IACtB;AAGA,QAAI,KAAK,QAAQ,YAAY;AAC3B,UAAI,CAAC,KAAK,UAAU,UAAU,SAAS,sBAAsB,GAAG;AAC9D,aAAK,iBAAiB;AAAA,MACxB;AAAA,IACF,OAAO;AAEL,WAAK,UAAU,UAAU,OAAO,sBAAsB;AAAA,IACxD;AAGA,QAAI,KAAK,QAAQ,WAAW,CAAC,KAAK,SAAS;AAEzC,WAAK,eAAe;AAAA,IACtB,WAAW,CAAC,KAAK,QAAQ,WAAW,KAAK,SAAS;AAEhD,WAAK,yBAAyB;AAC9B,WAAK,QAAQ,QAAQ;AACrB,WAAK,UAAU;AAAA,IACjB;AAGA,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB;AACd,UAAM,OAAO,KAAK,SAAS;AAC3B,UAAM,YAAY,KAAK,SAAS;AAChC,UAAM,aAAa,KAAK,gBAAgB,MAAM,SAAS;AAGvD,UAAM,gBAAgB,KAAK,UAAU,QAAQ,SAAS;AAGtD,UAAM,OAAO,eAAe,MAAM,MAAM,YAAY,KAAK,QAAQ,mBAAmB,KAAK,QAAQ,iBAAiB,aAAa;AAC/H,SAAK,QAAQ,YAAY,QAAQ;AAGjC,SAAK,2BAA2B;AAKhC,QAAI,KAAK,QAAQ,aAAa,KAAK,UAAU;AAC3C,WAAK,aAAa;AAAA,IACpB;AAGA,QAAI,KAAK,QAAQ,YAAY,KAAK,aAAa;AAC7C,WAAK,QAAQ,SAAS,MAAM,IAAI;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,6BAA6B;AAE3B,UAAM,aAAa,KAAK,QAAQ,iBAAiB,aAAa;AAG9D,aAAS,IAAI,GAAG,IAAI,WAAW,SAAS,GAAG,KAAK,GAAG;AACjD,YAAM,YAAY,WAAW,CAAC;AAC9B,YAAM,aAAa,WAAW,IAAI,CAAC;AAGnC,YAAM,aAAa,UAAU;AAC7B,YAAM,cAAc,WAAW;AAE/B,UAAI,CAAC,cAAc,CAAC;AAAa;AAGjC,gBAAU,MAAM,UAAU;AAC1B,iBAAW,MAAM,UAAU;AAG3B,iBAAW,UAAU,IAAI,iBAAiB;AAC1C,kBAAY,UAAU,IAAI,iBAAiB;AAAA,IAK7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,MAAM,WAAW;AAC/B,UAAM,QAAQ,KAAK,UAAU,GAAG,SAAS,EAAE,MAAM,IAAI;AACrD,WAAO,MAAM,SAAS;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,OAAO;AACjB,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,OAAO;AAEnB,QAAI,MAAM,QAAQ,OAAO;AACvB,YAAM,QAAQ,KAAK,SAAS;AAC5B,YAAM,MAAM,KAAK,SAAS;AAC1B,YAAM,QAAQ,KAAK,SAAS;AAG5B,UAAI,MAAM,YAAY,UAAU,KAAK;AACnC;AAAA,MACF;AAEA,YAAM,eAAe;AAGrB,UAAI,UAAU,OAAO,MAAM,UAAU;AAEnC,cAAM,SAAS,MAAM,UAAU,GAAG,KAAK;AACvC,cAAM,YAAY,MAAM,UAAU,OAAO,GAAG;AAC5C,cAAM,QAAQ,MAAM,UAAU,GAAG;AAEjC,cAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,cAAM,YAAY,MAAM,IAAI,UAAQ,KAAK,QAAQ,OAAO,EAAE,CAAC,EAAE,KAAK,IAAI;AAGtE,YAAI,SAAS,aAAa;AAExB,eAAK,SAAS,kBAAkB,OAAO,GAAG;AAC1C,mBAAS,YAAY,cAAc,OAAO,SAAS;AAAA,QACrD,OAAO;AAEL,eAAK,SAAS,QAAQ,SAAS,YAAY;AAC3C,eAAK,SAAS,iBAAiB;AAC/B,eAAK,SAAS,eAAe,QAAQ,UAAU;AAAA,QACjD;AAAA,MACF,WAAW,UAAU,KAAK;AAExB,cAAM,SAAS,MAAM,UAAU,GAAG,KAAK;AACvC,cAAM,YAAY,MAAM,UAAU,OAAO,GAAG;AAC5C,cAAM,QAAQ,MAAM,UAAU,GAAG;AAEjC,cAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,cAAM,WAAW,MAAM,IAAI,UAAQ,OAAO,IAAI,EAAE,KAAK,IAAI;AAGzD,YAAI,SAAS,aAAa;AAExB,eAAK,SAAS,kBAAkB,OAAO,GAAG;AAC1C,mBAAS,YAAY,cAAc,OAAO,QAAQ;AAAA,QACpD,OAAO;AAEL,eAAK,SAAS,QAAQ,SAAS,WAAW;AAC1C,eAAK,SAAS,iBAAiB;AAC/B,eAAK,SAAS,eAAe,QAAQ,SAAS;AAAA,QAChD;AAAA,MACF,OAAO;AAGL,YAAI,SAAS,aAAa;AACxB,mBAAS,YAAY,cAAc,OAAO,IAAI;AAAA,QAChD,OAAO;AAEL,eAAK,SAAS,QAAQ,MAAM,UAAU,GAAG,KAAK,IAAI,OAAO,MAAM,UAAU,GAAG;AAC5E,eAAK,SAAS,iBAAiB,KAAK,SAAS,eAAe,QAAQ;AAAA,QACtE;AAAA,MACF;AAGA,WAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AACjE;AAAA,IACF;AAGA,QAAI,MAAM,QAAQ,WAAW,CAAC,MAAM,YAAY,CAAC,MAAM,WAAW,CAAC,MAAM,WAAW,KAAK,QAAQ,YAAY;AAC3G,UAAI,KAAK,4BAA4B,GAAG;AACtC,cAAM,eAAe;AACrB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,UAAU,KAAK,UAAU,cAAc,KAAK;AAGlD,QAAI,CAAC,WAAW,KAAK,QAAQ,WAAW;AACtC,WAAK,QAAQ,UAAU,OAAO,IAAI;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,8BAA8B;AAC5B,UAAM,WAAW,KAAK;AACtB,UAAM,YAAY,SAAS;AAC3B,UAAM,UAAU,eAAe,eAAe,SAAS,OAAO,SAAS;AAEvE,QAAI,CAAC,WAAW,CAAC,QAAQ;AAAQ,aAAO;AAGxC,QAAI,QAAQ,QAAQ,KAAK,MAAM,MAAM,aAAa,QAAQ,cAAc;AACtE,WAAK,iBAAiB,OAAO;AAC7B,aAAO;AAAA,IACT;AAGA,QAAI,YAAY,QAAQ,gBAAgB,YAAY,QAAQ,SAAS;AACnE,WAAK,cAAc,SAAS,SAAS;AAAA,IACvC,OAAO;AAEL,WAAK,kBAAkB,OAAO;AAAA,IAChC;AAGA,QAAI,QAAQ,aAAa,YAAY;AACnC,WAAK,2BAA2B;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,SAAS;AAExB,SAAK,SAAS,kBAAkB,QAAQ,WAAW,QAAQ,YAAY;AACvE,aAAS,YAAY,QAAQ;AAG7B,SAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB,SAAS;AACzB,UAAM,UAAU,eAAe,kBAAkB,OAAO;AACxD,aAAS,YAAY,cAAc,OAAO,OAAO,OAAO;AAGxD,SAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,SAAS,WAAW;AAEhC,UAAM,kBAAkB,QAAQ,QAAQ,UAAU,YAAY,QAAQ,YAAY;AAGlF,SAAK,SAAS,kBAAkB,WAAW,QAAQ,OAAO;AAC1D,aAAS,YAAY,QAAQ;AAG7B,UAAM,UAAU,eAAe,kBAAkB,OAAO;AACxD,aAAS,YAAY,cAAc,OAAO,OAAO,UAAU,eAAe;AAG1E,UAAM,eAAe,KAAK,SAAS,iBAAiB,gBAAgB;AACpE,SAAK,SAAS,kBAAkB,cAAc,YAAY;AAG1D,SAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,6BAA6B;AAE3B,QAAI,KAAK,qBAAqB;AAC5B,mBAAa,KAAK,mBAAmB;AAAA,IACvC;AAGA,SAAK,sBAAsB,WAAW,MAAM;AAC1C,WAAK,oBAAoB;AAAA,IAC3B,GAAG,EAAE;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB;AACpB,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,YAAY,KAAK,SAAS;AAEhC,UAAM,WAAW,eAAe,cAAc,KAAK;AAEnD,QAAI,aAAa,OAAO;AAEtB,UAAI,SAAS;AACb,YAAM,WAAW,MAAM,MAAM,IAAI;AACjC,YAAM,WAAW,SAAS,MAAM,IAAI;AACpC,UAAI,YAAY;AAEhB,eAAS,IAAI,GAAG,IAAI,SAAS,UAAU,YAAY,WAAW,KAAK;AACjE,YAAI,SAAS,CAAC,MAAM,SAAS,CAAC,GAAG;AAC/B,gBAAM,OAAO,SAAS,CAAC,EAAE,SAAS,SAAS,CAAC,EAAE;AAC9C,cAAI,YAAY,SAAS,CAAC,EAAE,SAAS,WAAW;AAC9C,sBAAU;AAAA,UACZ;AAAA,QACF;AACA,qBAAa,SAAS,CAAC,EAAE,SAAS;AAAA,MACpC;AAGA,WAAK,SAAS,QAAQ;AACtB,YAAM,eAAe,YAAY;AACjC,WAAK,SAAS,kBAAkB,cAAc,YAAY;AAG1D,WAAK,SAAS,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAAA,IACnE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,OAAO;AAElB,SAAK,QAAQ,YAAY,KAAK,SAAS;AACvC,SAAK,QAAQ,aAAa,KAAK,SAAS;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW;AACT,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,OAAO;AACd,SAAK,SAAS,QAAQ;AACtB,SAAK,cAAc;AAGnB,QAAI,KAAK,QAAQ,YAAY;AAC3B,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cAAc,UAAU,QAAQ,MAAM;AAl5BhD;AAm5BM,UAAM,WAAW,KAAK;AACtB,QAAI,CAAC;AAAU,aAAO;AAEtB,UAAM,UAAS,UAAK,gBAAL,mBAAmB;AAClC,QAAI,CAAC,QAAQ;AACX,cAAQ,KAAK,6BAA6B,QAAQ,GAAG;AACrD,aAAO;AAAA,IACT;AAEA,aAAS,MAAM;AAEf,QAAI;AACF,YAAM,OAAO;AAAA,QACX,QAAQ;AAAA,QACR,UAAU,MAAM,KAAK,SAAS;AAAA,QAC9B,UAAU,CAAC,UAAU,KAAK,SAAS,KAAK;AAAA,QACxC;AAAA,MACF,CAAC;AAGD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,qBAAqB,QAAQ,YAAY,KAAK;AAC5D,WAAK,QAAQ,cAAc,IAAI,YAAY,gBAAgB;AAAA,QACzD,QAAQ,EAAE,UAAU,MAAM;AAAA,MAC5B,CAAC,CAAC;AACF,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,UAAU,CAAC,GAAG;AAC5B,UAAM,WAAW,KAAK,SAAS;AAC/B,QAAI,OAAO,eAAe,MAAM,UAAU,IAAI,OAAO,KAAK,QAAQ,eAAe;AAEjF,QAAI,QAAQ,WAAW;AAErB,aAAO,KAAK,QAAQ,iDAAiD,EAAE;AAEvE,aAAO,KAAK,QAAQ,kFAAkF,EAAE;AAExG,aAAO,KAAK,QAAQ,eAAe,EAAE;AAAA,IACvC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB;AACf,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAe;AACb,WAAO,KAAK,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACN,SAAK,SAAS,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACL,SAAK,SAAS,KAAK;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB;AACd,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,UAAU,CAAC,GAAG;AAn/BzB;AAo/BM,UAAM,sBAAqB,UAAK,YAAL,mBAAc;AACzC,SAAK,UAAU,KAAK,cAAc,EAAE,GAAG,KAAK,SAAS,GAAG,QAAQ,CAAC;AACjE,UAAM,sBAAsB,KAAK,WAC/B,KAAK,QAAQ,WACb,sBAAsB,oBAAoB,KAAK,QAAQ,cAAc;AAGvE,SAAK,mBAAmB;AAExB,QAAI,qBAAqB;AACvB,WAAK,yBAAyB;AAC9B,WAAK,QAAQ,QAAQ;AACrB,WAAK,UAAU;AACf,WAAK,eAAe;AAAA,IACtB;AAEA,SAAK,cAAc;AACnB,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,OAAO;AACd,SAAK,aAAa;AAClB,SAAK,gBAAgB;AAErB,QAAI,UAAU,QAAQ;AACpB,WAAK,WAAW;AAChB,WAAK,YAAY,iBAAiB,MAAM,CAAC;AAAA,IAC3C,OAAO;AACL,YAAM,WAAW,OAAO,UAAU,WAAW,SAAS,KAAK,IAAI;AAC/D,YAAM,YAAY,SAAS,QAAQ;AAEnC,UAAI,WAAW;AACb,aAAK,UAAU,aAAa,cAAc,SAAS;AAAA,MACrD;AAEA,UAAI,qCAAU,QAAQ;AACpB,aAAK,UAAU,MAAM,WAAW,eAAe,SAAS,MAAM;AAAA,MAChE;AAEA,WAAK,cAAc;AAAA,IACrB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,WAAW;AACrB,UAAM,WAAW,SAAS,SAAS;AACnC,SAAK,UAAU,aAAa,cAAc,MAAM;AAChD,SAAK,UAAU,aAAa,uBAAuB,SAAS;AAE5D,QAAI,qCAAU,QAAQ;AACpB,WAAK,UAAU,MAAM,WAAW,eAAe,SAAS,MAAM;AAAA,IAChE;AAEA,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa;AA1jCjB;AA2jCM,QAAI,CAAC,OAAO;AAAY;AAExB,cAAS,eAAe,IAAI,IAAI;AAEhC,QAAI,CAAC,UAAS,KAAK;AACjB,gBAAS,MAAM,OAAO,WAAW,8BAA8B;AAC/D,gBAAS,cAAc,CAAC,MAAM;AAC5B,cAAM,QAAQ,EAAE,UAAU,SAAS;AACnC,kBAAS,eAAe,QAAQ,UAAQ,KAAK,YAAY,KAAK,CAAC;AAAA,MACjE;AAGA,OAAC,eAAS,IAAI,oBAAoB,UAAS,IAAI,gBAA9C,mBAA4D;AAAA,QAC3D,UAAS;AAAA,QAAK;AAAA,QAAU,UAAS;AAAA;AAAA,IAErC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe;AAjlCnB;AAklCM,cAAS,eAAe,OAAO,IAAI;AAEnC,QAAI,UAAS,eAAe,SAAS,KAAK,UAAS,KAAK;AAEtD,OAAC,eAAS,IAAI,uBAAuB,UAAS,IAAI,mBAAjD,mBAAkE;AAAA,QACjE,UAAS;AAAA,QAAK;AAAA,QAAU,UAAS;AAAA;AAEnC,gBAAS,MAAM;AACf,gBAAS,cAAc;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,aAAa;AAC9B,SAAK,QAAQ,kBAAkB;AAC/B,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe;AACb,QAAI,CAAC,KAAK;AAAU;AAEpB,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,UAAM,QAAQ,MAAM;AACpB,UAAM,QAAQ,MAAM,MAAM,KAAK,EAAE,OAAO,OAAK,EAAE,SAAS,CAAC,EAAE;AAG3D,UAAM,iBAAiB,KAAK,SAAS;AACrC,UAAM,eAAe,MAAM,UAAU,GAAG,cAAc;AACtD,UAAM,oBAAoB,aAAa,MAAM,IAAI;AACjD,UAAM,cAAc,kBAAkB;AACtC,UAAM,gBAAgB,kBAAkB,kBAAkB,SAAS,CAAC,EAAE,SAAS;AAG/E,QAAI,KAAK,QAAQ,gBAAgB;AAC/B,WAAK,SAAS,YAAY,KAAK,QAAQ,eAAe;AAAA,QACpD;AAAA,QACA;AAAA,QACA,OAAO,MAAM;AAAA,QACb,MAAM;AAAA,QACN,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,OAAO;AAEL,WAAK,SAAS,YAAY;AAAA;AAAA;AAAA,oBAGd,KAAK,WAAW,KAAK,WAAW,MAAM,MAAM;AAAA;AAAA,4CAEpB,WAAW,SAAS,aAAa;AAAA;AAAA,IAEvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB;AAEjB,SAAK,UAAU,UAAU,IAAI,sBAAsB;AAGnD,SAAK,iBAAiB;AAGtB,SAAK,kBAAkB;AAGvB,SAAK,SAAS,iBAAiB,SAAS,MAAM,KAAK,kBAAkB,CAAC;AAGtE,WAAO,iBAAiB,UAAU,MAAM,KAAK,kBAAkB,CAAC;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB;AAClB,QAAI,CAAC,KAAK,QAAQ;AAAY;AAE9B,UAAM,WAAW,KAAK;AACtB,UAAM,UAAU,KAAK;AACrB,UAAM,UAAU,KAAK;AAGrB,UAAM,WAAW,OAAO,iBAAiB,QAAQ;AACjD,UAAM,aAAa,WAAW,SAAS,UAAU;AACjD,UAAM,gBAAgB,WAAW,SAAS,aAAa;AAGvD,UAAM,YAAY,SAAS;AAG3B,aAAS,MAAM,YAAY,UAAU,QAAQ,WAAW;AAGxD,QAAI,YAAY,SAAS;AAGzB,QAAI,KAAK,QAAQ,WAAW;AAC1B,YAAM,YAAY,SAAS,KAAK,QAAQ,SAAS;AACjD,kBAAY,KAAK,IAAI,WAAW,SAAS;AAAA,IAC3C;AAGA,QAAI,WAAW;AACf,QAAI,KAAK,QAAQ,WAAW;AAC1B,YAAM,YAAY,SAAS,KAAK,QAAQ,SAAS;AACjD,UAAI,YAAY,WAAW;AACzB,oBAAY;AACZ,mBAAW;AAAA,MACb;AAAA,IACF;AAGA,UAAM,WAAW,YAAY;AAC7B,aAAS,MAAM,YAAY,UAAU,UAAU,WAAW;AAC1D,aAAS,MAAM,YAAY,cAAc,UAAU,WAAW;AAE9D,YAAQ,MAAM,YAAY,UAAU,UAAU,WAAW;AACzD,YAAQ,MAAM,YAAY,cAAc,UAAU,WAAW;AAE7D,YAAQ,MAAM,YAAY,UAAU,UAAU,WAAW;AAGzD,aAAS,YAAY;AACrB,YAAQ,YAAY;AAGpB,QAAI,KAAK,mBAAmB,WAAW;AACrC,WAAK,iBAAiB;AAAA,IAExB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,MAAM;AACd,SAAK,QAAQ,YAAY;AAEzB,QAAI,QAAQ,CAAC,KAAK,UAAU;AAE1B,WAAK,WAAW,SAAS,cAAc,KAAK;AAC5C,WAAK,SAAS,YAAY;AAC1B,WAAK,UAAU,YAAY,KAAK,QAAQ;AACxC,WAAK,aAAa;AAAA,IACpB,WAAW,QAAQ,KAAK,UAAU;AAEhC,WAAK,aAAa;AAAA,IACpB,WAAW,CAAC,QAAQ,KAAK,UAAU;AAEjC,WAAK,SAAS,OAAO;AACrB,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB;AACnB,SAAK,UAAU,QAAQ,OAAO;AAC9B,SAAK,cAAc;AAGnB,0BAAsB,MAAM;AAC1B,WAAK,SAAS,YAAY,KAAK,QAAQ;AACvC,WAAK,SAAS,aAAa,KAAK,QAAQ;AAAA,IAC1C,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB;AAClB,SAAK,UAAU,QAAQ,OAAO;AAG9B,QAAI,KAAK,SAAS;AAChB,YAAM,YAAY,KAAK,UAAU,cAAc,8BAA8B;AAC7E,UAAI,WAAW;AACb,kBAAU,UAAU,OAAO,QAAQ;AACnC,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB;AAChB,SAAK,UAAU,QAAQ,OAAO;AAC9B,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAER,SAAK,aAAa;AAGlB,SAAK,QAAQ,mBAAmB;AAChC,cAAS,UAAU,OAAO,KAAK,OAAO;AAGtC,QAAI,KAAK,WAAW;AAClB,WAAK,UAAU,QAAQ;AAAA,IACzB;AAGA,QAAI,KAAK,SAAS;AAChB,YAAM,UAAU,KAAK,SAAS;AAC9B,WAAK,QAAQ,OAAO;AAGpB,WAAK,QAAQ,cAAc;AAAA,IAC7B;AAEA,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,KAAK,QAAQ,UAAU,CAAC,GAAG;AAChC,WAAO,IAAI,UAAS,QAAQ,OAAO;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,aAAa,UAAU,WAAW,CAAC,GAAG;AAC3C,UAAM,WAAW,SAAS,iBAAiB,QAAQ;AACnD,WAAO,MAAM,KAAK,QAAQ,EAAE,IAAI,QAAM;AACpC,YAAM,UAAU,EAAE,GAAG,SAAS;AAG9B,iBAAW,QAAQ,GAAG,YAAY;AAChC,YAAI,KAAK,KAAK,WAAW,UAAU,GAAG;AACpC,gBAAM,QAAQ,KAAK,KAAK,MAAM,CAAC;AAC/B,gBAAM,MAAM,MAAM,QAAQ,aAAa,CAAC,GAAG,MAAM,EAAE,YAAY,CAAC;AAChE,kBAAQ,GAAG,IAAI,UAAS,gBAAgB,KAAK,KAAK;AAAA,QACpD;AAAA,MACF;AAEA,aAAO,IAAI,UAAS,IAAI,OAAO;AAAA,IACjC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,gBAAgB,OAAO;AAC5B,QAAI,UAAU;AAAQ,aAAO;AAC7B,QAAI,UAAU;AAAS,aAAO;AAC9B,QAAI,UAAU;AAAQ,aAAO;AAC7B,QAAI,UAAU,MAAM,CAAC,MAAM,OAAO,KAAK,CAAC;AAAG,aAAO,OAAO,KAAK;AAC9D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,SAAS;AAC1B,WAAO,QAAQ,oBAAoB,UAAS,UAAU,IAAI,OAAO,KAAK;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,aAAa;AAClB,UAAM,WAAW,SAAS,iBAAiB,0BAA0B;AACrE,aAAS,QAAQ,aAAW;AAC1B,YAAM,WAAW,UAAS,YAAY,OAAO;AAC7C,UAAI,UAAU;AACZ,iBAAS,QAAQ;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,aAAa,QAAQ,OAAO;AACjC,QAAI,UAAS,kBAAkB,CAAC;AAAO;AAGvC,UAAM,WAAW,SAAS,cAAc,uBAAuB;AAC/D,QAAI,UAAU;AACZ,eAAS,OAAO;AAAA,IAClB;AAGA,UAAM,QAAQ,UAAS,gBAAgB;AACvC,UAAM,SAAS,eAAe,EAAE,MAAM,CAAC;AACvC,UAAM,UAAU,SAAS,cAAc,OAAO;AAC9C,YAAQ,YAAY;AACpB,YAAQ,cAAc;AACtB,aAAS,KAAK,YAAY,OAAO;AAEjC,cAAS,iBAAiB;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,kBAAkB,WAAW,SAAS,OAAO;AAElD,UAAM,aAAa,SAAS,iBAAiB,qBAAqB;AAClE,UAAM,WAAW,SAAS,iBAAiB,mBAAmB;AAE9D,eAAW,QAAQ,QAAM;AACvB,UAAI,QAAQ;AACV,WAAG,aAAa,cAAc,MAAM;AACpC,WAAG,aAAa,uBAAuB,SAAS;AAAA,MAClD,OAAO;AACL,WAAG,aAAa,cAAc,SAAS;AAAA,MACzC;AAAA,IACF,CAAC;AAED,aAAS,QAAQ,aAAW;AAt7ClC;AAu7CQ,UAAI,CAAC,QAAQ,QAAQ,qBAAqB,GAAG;AAC3C,YAAI,QAAQ;AACV,kBAAQ,aAAa,cAAc,MAAM;AACzC,kBAAQ,aAAa,uBAAuB,SAAS;AAAA,QACvD,OAAO;AACL,kBAAQ,aAAa,cAAc,SAAS;AAAA,QAC9C;AAAA,MACF;AACA,oBAAQ,cAAR,mBAAmB;AAAA,IACrB,CAAC;AAGD,aAAS,iBAAiB,iBAAiB,EAAE,QAAQ,QAAM;AAn8CjE;AAo8CQ,UAAI,QAAQ;AACV,iBAAG,iBAAH,4BAAkB,SAAS;AAC3B,iBAAG,iBAAH,4BAAkB,uBAAuB;AAAA,MAC3C,OAAO;AACL,iBAAG,iBAAH,4BAAkB,SAAS;AAAA,MAC7B;AACA,eAAG,iBAAH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,SAAS,OAAO,eAAe,MAAM;AAE1C,cAAS,mBAAmB;AAG5B,QAAI,UAAU,QAAQ;AACpB,gBAAS,iBAAiB;AAC1B,gBAAS,kBAAkB,iBAAiB,MAAM,GAAG,cAAc,IAAI;AAAA,IACzE,OAAO;AAEL,UAAI,WAAW,OAAO,UAAU,WAAW,SAAS,KAAK,IAAI;AAG7D,UAAI,cAAc;AAChB,mBAAW,WAAW,UAAU,YAAY;AAAA,MAC9C;AAGA,gBAAS,eAAe;AAGxB,gBAAS,aAAa,IAAI;AAG1B,YAAM,YAAY,SAAS,QAAQ;AACnC,UAAI,WAAW;AACb,kBAAS,kBAAkB,SAAS;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,kBAAkB,WAAW,eAAe,MAAM,SAAS,OAAO;AACvE,QAAI,WAAW,SAAS,SAAS;AAGjC,QAAI,cAAc;AAChB,iBAAW,WAAW,UAAU,YAAY;AAAA,IAC9C;AAGA,cAAS,eAAe;AAGxB,cAAS,aAAa,IAAI;AAG1B,cAAS,kBAAkB,WAAW,MAAM;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB;AA/gD9B;AAghDM,QAAI,CAAC,OAAO,cAAc,UAAS;AAAe;AAElD,cAAS,gBAAgB,OAAO,WAAW,8BAA8B;AACzE,cAAS,sBAAsB,CAAC,MAAM;AACpC,gBAAS,kBAAkB,EAAE,UAAU,SAAS,SAAS,MAAM,IAAI;AAAA,IACrE;AAGA,KAAC,eAAS,cAAc,oBAAoB,UAAS,cAAc,gBAAlE,mBAAgF;AAAA,MAC/E,UAAS;AAAA,MAAe;AAAA,MAAU,UAAS;AAAA;AAAA,EAE/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,qBAAqB;AAjiDhC;AAkiDM,QAAI,UAAS,iBAAiB,UAAS,qBAAqB;AAE1D,OAAC,eAAS,cAAc,uBAAuB,UAAS,cAAc,mBAArE,mBAAsF;AAAA,QACrF,UAAS;AAAA,QAAe;AAAA,QAAU,UAAS;AAAA;AAE7C,gBAAS,gBAAgB;AACzB,gBAAS,sBAAsB;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,aAAa;AACrC,mBAAe,mBAAmB,WAAW;AAG7C,aAAS,iBAAiB,mBAAmB,EAAE,QAAQ,aAAW;AAChE,YAAM,WAAW,QAAQ;AACzB,UAAI,YAAY,SAAS,eAAe;AACtC,iBAAS,cAAc;AAAA,MACzB;AAAA,IACF,CAAC;AAGD,aAAS,iBAAiB,iBAAiB,EAAE,QAAQ,kBAAgB;AACnE,UAAI,OAAO,aAAa,cAAc,YAAY;AAChD,cAAM,WAAW,aAAa,UAAU;AACxC,YAAI,YAAY,SAAS,eAAe;AACtC,mBAAS,cAAc;AAAA,QACzB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,gBAAgB,WAAW;AAChC,mBAAe,gBAAgB,SAAS;AAGxC,aAAS,iBAAiB,mBAAmB,EAAE,QAAQ,aAAW;AAChE,YAAM,WAAW,QAAQ;AACzB,UAAI,YAAY,SAAS,eAAe;AACtC,iBAAS,cAAc;AAAA,MACzB;AAAA,IACF,CAAC;AAED,aAAS,iBAAiB,iBAAiB,EAAE,QAAQ,kBAAgB;AACnE,UAAI,OAAO,aAAa,cAAc,YAAY;AAChD,cAAM,WAAW,aAAa,UAAU;AACxC,YAAI,YAAY,SAAS,eAAe;AACtC,mBAAS,cAAc;AAAA,QACzB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,sBAAsB;AAC3B,QAAI,UAAS;AAA4B;AAGzC,aAAS,iBAAiB,SAAS,CAAC,MAAM;AACxC,UAAI,EAAE,UAAU,EAAE,OAAO,aAAa,EAAE,OAAO,UAAU,SAAS,gBAAgB,GAAG;AACnF,cAAM,UAAU,EAAE,OAAO,QAAQ,mBAAmB;AACpD,cAAM,WAAW,mCAAS;AAC1B,YAAI;AAAU,mBAAS,YAAY,CAAC;AAAA,MACtC;AAAA,IACF,CAAC;AAGD,aAAS,iBAAiB,WAAW,CAAC,MAAM;AAC1C,UAAI,EAAE,UAAU,EAAE,OAAO,aAAa,EAAE,OAAO,UAAU,SAAS,gBAAgB,GAAG;AACnF,cAAM,UAAU,EAAE,OAAO,QAAQ,mBAAmB;AACpD,cAAM,WAAW,mCAAS;AAC1B,YAAI;AAAU,mBAAS,cAAc,CAAC;AAAA,MACxC;AAAA,IACF,CAAC;AAGD,aAAS,iBAAiB,UAAU,CAAC,MAAM;AACzC,UAAI,EAAE,UAAU,EAAE,OAAO,aAAa,EAAE,OAAO,UAAU,SAAS,gBAAgB,GAAG;AACnF,cAAM,UAAU,EAAE,OAAO,QAAQ,mBAAmB;AACpD,cAAM,WAAW,mCAAS;AAC1B,YAAI;AAAU,mBAAS,aAAa,CAAC;AAAA,MACvC;AAAA,IACF,GAAG,IAAI;AAGP,aAAS,iBAAiB,mBAAmB,CAAC,MAAM;AAClD,YAAM,gBAAgB,SAAS;AAC/B,UAAI,iBAAiB,cAAc,UAAU,SAAS,gBAAgB,GAAG;AACvE,cAAM,UAAU,cAAc,QAAQ,mBAAmB;AACzD,cAAM,WAAW,mCAAS;AAC1B,YAAI,UAAU;AAEZ,cAAI,SAAS,QAAQ,aAAa,SAAS,UAAU;AACnD,qBAAS,aAAa;AAAA,UACxB;AAEA,uBAAa,SAAS,iBAAiB;AACvC,mBAAS,oBAAoB,WAAW,MAAM;AAC5C,qBAAS,cAAc;AAAA,UACzB,GAAG,EAAE;AAAA,QACP;AAAA,MACF;AAAA,IACF,CAAC;AAED,cAAS,6BAA6B;AAAA,EACxC;AACJ;AAAA;AA7kDI,cAFE,WAEK,aAAY,oBAAI,QAAQ;AAC/B,cAHE,WAGK,kBAAiB;AACxB,cAJE,WAIK,8BAA6B;AACpC,cALE,WAKK,iBAAgB;AACvB,cANE,WAMK,OAAM;AAAA;AACb,cAPE,WAOK,eAAc;AAAA;AACrB,cARE,WAQK,kBAAiB,oBAAI,IAAI;AAAA;AAChC,cATE,WASK,iBAAgB;AAAA;AACvB,cAVE,WAUK,uBAAsB;AAVjC,IAAM,WAAN;AAklDA,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAG5B,SAAS,SAAS,EAAE,OAAO,MAAM,SAAS,MAAM,EAAE;AAClD,SAAS,WAAW;AAGpB,SAAS,eAAe;AAGxB,IAAO,mBAAQ;", + "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n const setTheme = (el) => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n };\n \n document.querySelectorAll('.overtype-container').forEach(setTheme);\n \n document.querySelectorAll('.overtype-wrapper').forEach(w => {\n if (!w.closest('.overtype-container')) setTheme(w);\n w._instance?.updatePreview();\n });\n \n document.querySelectorAll('overtype-editor').forEach(wc => {\n wc.setAttribute?.(isAuto ? 'theme' : 'theme', isAuto ? 'auto' : themeName);\n if (isAuto) wc.setAttribute?.('data-resolved-theme', themeName);\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], + "mappings": "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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons"] } diff --git a/dist/overtype.js b/dist/overtype.js index b66d407..0dc3228 100644 --- a/dist/overtype.js +++ b/dist/overtype.js @@ -4428,37 +4428,27 @@ ${blockSuffix}` : suffix; * @private */ static _updateThemeAttrs(themeName, isAuto = false) { - const containers = document.querySelectorAll(".overtype-container"); - const wrappers = document.querySelectorAll(".overtype-wrapper"); - containers.forEach((el) => { + const setTheme = (el) => { if (isAuto) { el.setAttribute("data-theme", "auto"); el.setAttribute("data-resolved-theme", themeName); } else { el.setAttribute("data-theme", themeName); } - }); - wrappers.forEach((wrapper) => { + }; + document.querySelectorAll(".overtype-container").forEach(setTheme); + document.querySelectorAll(".overtype-wrapper").forEach((w) => { var _a; - if (!wrapper.closest(".overtype-container")) { - if (isAuto) { - wrapper.setAttribute("data-theme", "auto"); - wrapper.setAttribute("data-resolved-theme", themeName); - } else { - wrapper.setAttribute("data-theme", themeName); - } - } - (_a = wrapper._instance) == null ? void 0 : _a.updatePreview(); + if (!w.closest(".overtype-container")) + setTheme(w); + (_a = w._instance) == null ? void 0 : _a.updatePreview(); }); document.querySelectorAll("overtype-editor").forEach((wc) => { - var _a, _b, _c, _d; - if (isAuto) { - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", "auto"); + var _a, _b, _c; + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); - } else { - (_c = wc.setAttribute) == null ? void 0 : _c.call(wc, "theme", themeName); - } - (_d = wc.refreshTheme) == null ? void 0 : _d.call(wc); + (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); }); } /** diff --git a/dist/overtype.js.map b/dist/overtype.js.map index e59af0c..2c7dc04 100644 --- a/dist/overtype.js.map +++ b/dist/overtype.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/overtype.js", "../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js"], - "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n // Single query for containers and wrappers\n const containers = document.querySelectorAll('.overtype-container');\n const wrappers = document.querySelectorAll('.overtype-wrapper');\n \n containers.forEach(el => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n });\n \n wrappers.forEach(wrapper => {\n if (!wrapper.closest('.overtype-container')) {\n if (isAuto) {\n wrapper.setAttribute('data-theme', 'auto');\n wrapper.setAttribute('data-resolved-theme', themeName);\n } else {\n wrapper.setAttribute('data-theme', themeName);\n }\n }\n wrapper._instance?.updatePreview();\n });\n \n // Update web components\n document.querySelectorAll('overtype-editor').forEach(wc => {\n if (isAuto) {\n wc.setAttribute?.('theme', 'auto');\n wc.setAttribute?.('data-resolved-theme', themeName);\n } else {\n wc.setAttribute?.('theme', themeName);\n }\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], - "mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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", + "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n const setTheme = (el) => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n };\n \n document.querySelectorAll('.overtype-container').forEach(setTheme);\n \n document.querySelectorAll('.overtype-wrapper').forEach(w => {\n if (!w.closest('.overtype-container')) setTheme(w);\n w._instance?.updatePreview();\n });\n \n document.querySelectorAll('overtype-editor').forEach(wc => {\n wc.setAttribute?.(isAuto ? 'theme' : 'theme', isAuto ? 'auto' : themeName);\n if (isAuto) wc.setAttribute?.('data-resolved-theme', themeName);\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], + "mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons"] } diff --git a/dist/overtype.min.js b/dist/overtype.min.js index 048a5d8..626767a 100644 --- a/dist/overtype.min.js +++ b/dist/overtype.min.js @@ -5,13 +5,13 @@ * @author David Miranda * https://github.com/panphora/overtype */ -var OverType=(()=>{var O=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var qe=(o,e,t)=>e in o?O(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Ve=(o,e)=>{for(var t in e)O(o,t,{get:e[t],enumerable:!0})},Ue=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!Re.call(o,i)&&i!==t&&O(o,i,{get:()=>e[i],enumerable:!(n=Fe(e,i))||n.enumerable});return o};var De=o=>Ue(O({},"__esModule",{value:!0}),o);var E=(o,e,t)=>(qe(o,typeof e!="symbol"?e+"":e,t),t);var at={};Ve(at,{OverType:()=>I,default:()=>st,defaultToolbarButtons:()=>N,toolbarButtons:()=>k});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,n=>t[n])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,n,i)=>{let r=n.length;return`${n} ${i}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,n)=>`> ${n}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(n,i,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${i}
  • ${s}
  • `}else return`${i}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),n=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>n.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,n,i)=>{let r=`--link-${this.linkIndex++}`;return`
    [${n}](${i})`})}static identifyAndProtectSanctuaries(e){let t=new Map,n=0,i=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let h=a.index+a[0].indexOf("](")+2,m=h+a[2].length;r.push({start:h,end:m})}let c=new RegExp("(?p>=g.start&&h<=g.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((p,h)=>h.index-p.index),l.forEach(p=>{let h=`\uE000${n++}\uE001`;t.set(h,{type:"code",original:p.match,openTicks:p.openTicks,content:p.content,closeTicks:p.closeTicks}),i=i.substring(0,p.index)+h+i.substring(p.index+p.match.length)}),i=i.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(p,h,m)=>{let g=`\uE000${n++}\uE001`;return t.set(g,{type:"link",original:p,linkText:h,url:m}),g}),{protectedText:i,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((i,r)=>{let s=e.indexOf(i),a=e.indexOf(r);return s-a}).forEach(i=>{let r=t.get(i),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,p)=>{if(a.includes(p)&&l.type==="code"){let h=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(p,h)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let c=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(i,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:n}=this.identifyAndProtectSanctuaries(e),i=t;return i=this.parseStrikethrough(i),i=this.parseBold(i),i=this.parseItalic(i),i=this.restoreAndTransformSanctuaries(i,n),i}static parseLine(e,t=!1){let n=this.escapeHtml(e);n=this.preserveIndentation(n,e);let i=this.parseHorizontalRule(n);if(i)return i;let r=this.parseCodeBlock(n);return r||(n=this.parseHeader(n),n=this.parseBlockquote(n),n=this.parseTaskList(n,t),n=this.parseBulletList(n),n=this.parseNumberedList(n),n=this.parseInlineElements(n),n.trim()===""?"
     
    ":`
    ${n}
    `)}static parse(e,t=-1,n=!1,i,r=!1){this.resetLinkIndex();let s=e.split(` -`),a=!1,d=s.map((l,p)=>{if(n&&p===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let m=this.escapeHtml(l);return`
    ${this.preserveIndentation(m,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,i)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let n=document.createElement("div");n.innerHTML=e;let i=null,r=null,s=null,a=!1,c=Array.from(n.children);for(let d=0;d0&&(s._codeContent+=` +var OverType=(()=>{var O=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var Re=Object.prototype.hasOwnProperty;var qe=(o,e,t)=>e in o?O(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var Ve=(o,e)=>{for(var t in e)O(o,t,{get:e[t],enumerable:!0})},Ue=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!Re.call(o,i)&&i!==t&&O(o,i,{get:()=>e[i],enumerable:!(n=Fe(e,i))||n.enumerable});return o};var De=o=>Ue(O({},"__esModule",{value:!0}),o);var E=(o,e,t)=>(qe(o,typeof e!="symbol"?e+"":e,t),t);var at={};Ve(at,{OverType:()=>I,default:()=>st,defaultToolbarButtons:()=>N,toolbarButtons:()=>k});var S=class{static resetLinkIndex(){this.linkIndex=0}static setCodeHighlighter(e){this.codeHighlighter=e}static setCustomSyntax(e){this.customSyntax=e}static applyCustomSyntax(e){return this.customSyntax?this.customSyntax(e):e}static escapeHtml(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,n=>t[n])}static preserveIndentation(e,t){let i=t.match(/^(\s*)/)[1].replace(/ /g," ");return e.replace(/^\s*/,i)}static parseHeader(e){return e.replace(/^(#{1,3})\s(.+)$/,(t,n,i)=>{let r=n.length;return`${n} ${i}`})}static parseHorizontalRule(e){return e.match(/^(-{3,}|\*{3,}|_{3,})$/)?`
    ${e}
    `:null}static parseBlockquote(e){return e.replace(/^> (.+)$/,(t,n)=>`> ${n}`)}static parseBulletList(e){return e.replace(/^((?: )*)([-*+])\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseTaskList(e,t=!1){return e.replace(/^((?: )*)-\s+\[([ xX])\]\s+(.+)$/,(n,i,r,s)=>{if(t){let a=r.toLowerCase()==="x";return`${i}
  • ${s}
  • `}else return`${i}
  • - [${r}] ${s}
  • `})}static parseNumberedList(e){return e.replace(/^((?: )*)(\d+\.)\s(.+)$/,(t,n,i,r)=>`${n}
  • ${i} ${r}
  • `)}static parseCodeBlock(e){return/^`{3}[^`]*$/.test(e)?`
    ${e}
    `:null}static parseBold(e){return e=e.replace(/\*\*(.+?)\*\*/g,'**$1**'),e=e.replace(/__(.+?)__/g,'__$1__'),e}static parseItalic(e){return e=e.replace(new RegExp("(?])\\*(?!\\*)(.+?)(?*$1*'),e=e.replace(new RegExp("(?<=^|\\s)_(?!_)(.+?)(?_$1_'),e}static parseStrikethrough(e){return e=e.replace(new RegExp("(?~~$1~~'),e=e.replace(new RegExp("(?~$1~'),e}static parseInlineCode(e){return e.replace(new RegExp("(?$1$2$3')}static sanitizeUrl(e){let t=e.trim(),n=t.toLowerCase(),r=["http://","https://","mailto:","ftp://","ftps://"].some(a=>n.startsWith(a)),s=t.startsWith("/")||t.startsWith("#")||t.startsWith("?")||t.startsWith(".")||!t.includes(":")&&!t.includes("//");return r||s?e:"#"}static parseLinks(e){return e.replace(/\[(.+?)\]\((.+?)\)/g,(t,n,i)=>{let r=`--link-${this.linkIndex++}`;return`[${n}](${i})`})}static identifyAndProtectSanctuaries(e){let t=new Map,n=0,i=e,r=[],s=/\[([^\]]+)\]\(([^)]+)\)/g,a;for(;(a=s.exec(e))!==null;){let u=a.index+a[0].indexOf("](")+2,m=u+a[2].length;r.push({start:u,end:m})}let p=new RegExp("(?c>=g.start&&u<=g.end)||l.push({match:d[0],index:d.index,openTicks:d[1],content:d[2],closeTicks:d[3]})}return l.sort((c,u)=>u.index-c.index),l.forEach(c=>{let u=`\uE000${n++}\uE001`;t.set(u,{type:"code",original:c.match,openTicks:c.openTicks,content:c.content,closeTicks:c.closeTicks}),i=i.substring(0,c.index)+u+i.substring(c.index+c.match.length)}),i=i.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(c,u,m)=>{let g=`\uE000${n++}\uE001`;return t.set(g,{type:"link",original:c,linkText:u,url:m}),g}),{protectedText:i,sanctuaries:t}}static restoreAndTransformSanctuaries(e,t){return Array.from(t.keys()).sort((i,r)=>{let s=e.indexOf(i),a=e.indexOf(r);return s-a}).forEach(i=>{let r=t.get(i),s;if(r.type==="code")s=`${r.openTicks}${r.content}${r.closeTicks}`;else if(r.type==="link"){let a=r.linkText;t.forEach((l,c)=>{if(a.includes(c)&&l.type==="code"){let u=`${l.openTicks}${l.content}${l.closeTicks}`;a=a.replace(c,u)}}),a=this.parseStrikethrough(a),a=this.parseBold(a),a=this.parseItalic(a);let p=`--link-${this.linkIndex++}`;s=`[${a}](${r.url})`}e=e.replace(i,s)}),e}static parseInlineElements(e){let{protectedText:t,sanctuaries:n}=this.identifyAndProtectSanctuaries(e),i=t;return i=this.parseStrikethrough(i),i=this.parseBold(i),i=this.parseItalic(i),i=this.restoreAndTransformSanctuaries(i,n),i}static parseLine(e,t=!1){let n=this.escapeHtml(e);n=this.preserveIndentation(n,e);let i=this.parseHorizontalRule(n);if(i)return i;let r=this.parseCodeBlock(n);return r||(n=this.parseHeader(n),n=this.parseBlockquote(n),n=this.parseTaskList(n,t),n=this.parseBulletList(n),n=this.parseNumberedList(n),n=this.parseInlineElements(n),n.trim()===""?"
     
    ":`
    ${n}
    `)}static parse(e,t=-1,n=!1,i,r=!1){this.resetLinkIndex();let s=e.split(` +`),a=!1,d=s.map((l,c)=>{if(n&&c===t)return`
    ${this.escapeHtml(l)||" "}
    `;if(/^```[^`]*$/.test(l))return a=!a,this.applyCustomSyntax(this.parseLine(l,r));if(a){let m=this.escapeHtml(l);return`
    ${this.preserveIndentation(m,l)||" "}
    `}return this.applyCustomSyntax(this.parseLine(l,r))}).join("");return this.postProcessHTML(d,i)}static postProcessHTML(e,t){if(typeof document>"u"||!document)return this.postProcessHTMLManual(e,t);let n=document.createElement("div");n.innerHTML=e;let i=null,r=null,s=null,a=!1,p=Array.from(n.children);for(let d=0;d0&&(s._codeContent+=` `);let g=l.textContent.replace(/\u00A0/g," ");s._codeContent+=g,m.textContent.length>0&&(m.textContent+=` -`),m.textContent+=g,l.remove();continue}let h=null;if(l.tagName==="DIV"&&(h=l.querySelector("li")),h){let m=h.classList.contains("bullet-list"),g=h.classList.contains("ordered-list");if(!m&&!g){i=null,r=null;continue}let f=m?"ul":"ol";(!i||r!==f)&&(i=document.createElement(f),n.insertBefore(i,l),r=f);let v=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))v.push(y.cloneNode(!0));else if(y===h)break;v.forEach(y=>{h.insertBefore(y,h.firstChild)}),i.appendChild(h),l.remove()}else i=null,r=null}return n.innerHTML}static postProcessHTMLManual(e,t){let n=e;n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    • /,`
    • ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(c=>{let d=c.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let p=d[1];return l[0].replace(/
    2. /,`
    3. ${p}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let i=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return n=n.replace(i,(r,s,a,c)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(v=>v.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` -`),p=s.slice(3).trim(),h=p?` class="language-${p}"`:"",m=l,g=t||this.codeHighlighter;if(g)try{let v=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=g(v,p);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(m=y)}catch(v){console.warn("Code highlighting failed:",v)}let f=`
    ${s}
    `;return f+=`
    ${m}
    `,f+=`
    ${c}
    `,f}),n}static getListContext(e,t){let n=e.split(` -`),i=0,r=0,s=0;for(let h=0;h=t){r=h,s=i;break}i+=m+1}let a=n[r],c=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:c,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:c,markerEndPos:s+l[1].length+l[2].length+1};let p=a.match(this.LIST_PATTERNS.numbered);return p?{inList:!0,listType:"numbered",indent:p[1],marker:parseInt(p[2]),content:p[3],lineStart:s,lineEnd:c,markerEndPos:s+p[1].length+p[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:c,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` -`),n=new Map,i=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let c=a[1],d=c.length,l=a[3];i||n.clear();let p=(n.get(d)||0)+1;n.set(d,p);for(let[h]of n)h>d&&n.delete(h);return i=!0,`${c}${p}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(i=!1,n.clear()),s}).join(` +`),m.textContent+=g,l.remove();continue}let u=null;if(l.tagName==="DIV"&&(u=l.querySelector("li")),u){let m=u.classList.contains("bullet-list"),g=u.classList.contains("ordered-list");if(!m&&!g){i=null,r=null;continue}let f=m?"ul":"ol";(!i||r!==f)&&(i=document.createElement(f),n.insertBefore(i,l),r=f);let v=[];for(let y of l.childNodes)if(y.nodeType===3&&y.textContent.match(/^\u00A0+$/))v.push(y.cloneNode(!0));else if(y===u)break;v.forEach(y=>{u.insertBefore(y,u.firstChild)}),i.appendChild(u),l.remove()}else i=null,r=null}return n.innerHTML}static postProcessHTMLManual(e,t){let n=e;n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(p=>{let d=p.match(/
      ((?: )*)
    • .*?<\/li>/);if(d&&l){let c=d[1];return l[0].replace(/
    • /,`
    • ${c}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r}),n=n.replace(/((?:
    (?: )*
  • .*?<\/li><\/div>\s*)+)/gs,r=>{let s=r.match(/
    (?: )*
  • .*?<\/li><\/div>/gs)||[];return s.length>0?"
      "+s.map(p=>{let d=p.match(/
      ((?: )*)
    1. .*?<\/li>/);if(d&&l){let c=d[1];return l[0].replace(/
    2. /,`
    3. ${c}`)}return l?l[0]:""}).filter(Boolean).join("")+"
    ":r});let i=/
    (```[^<]*)<\/span><\/div>(.*?)
    (```)<\/span><\/div>/gs;return n=n.replace(i,(r,s,a,p)=>{let l=(a.match(/
    (.*?)<\/div>/gs)||[]).map(v=>v.replace(/
    (.*?)<\/div>/s,"$1").replace(/ /g," ")).join(` +`),c=s.slice(3).trim(),u=c?` class="language-${c}"`:"",m=l,g=t||this.codeHighlighter;if(g)try{let v=l.replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&"),y=g(v,c);y&&typeof y.then=="function"?console.warn("Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering."):y&&typeof y=="string"&&y.trim()&&(m=y)}catch(v){console.warn("Code highlighting failed:",v)}let f=`
    ${s}
    `;return f+=`
    ${m}
    `,f+=`
    ${p}
    `,f}),n}static getListContext(e,t){let n=e.split(` +`),i=0,r=0,s=0;for(let u=0;u=t){r=u,s=i;break}i+=m+1}let a=n[r],p=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:p,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:p,markerEndPos:s+l[1].length+l[2].length+1};let c=a.match(this.LIST_PATTERNS.numbered);return c?{inList:!0,listType:"numbered",indent:c[1],marker:parseInt(c[2]),content:c[3],lineStart:s,lineEnd:p,markerEndPos:s+c[1].length+c[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:p,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` +`),n=new Map,i=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let p=a[1],d=p.length,l=a[3];i||n.clear();let c=(n.get(d)||0)+1;n.set(d,c);for(let[u]of n)u>d&&n.delete(u);return i=!0,`${p}${c}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(i=!1,n.clear()),s}).join(` `)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.performAction(i,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ee={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},We={name:"auto",colors:A.colors},te={solar:A,cave:ee,auto:We,light:A,dark:ee};function M(o){return typeof o=="string"?{...te[o]||te.solar,name:o}:o}var j=null;function K(o){return o!=="auto"?o:(!j&&window.matchMedia&&(j=window.matchMedia("(prefers-color-scheme: dark)")),j!=null&&j.matches?"cave":"solar")}function _(o){let e=[];for(let[t,n]of Object.entries(o)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${n};`)}return e.join(` `)}function G(o,e={}){return{...o,colors:{...o.colors,...e}}}function ne(o={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:n='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:s={}}=o,a=Object.keys(s).length>0?` @media (max-width: 640px) { @@ -21,7 +21,7 @@ var OverType=(()=>{var O=Object.defineProperty;var Fe=Object.getOwnPropertyDescr `)} } } - `:"",c=r&&r.colors?_(r.colors):"";return` + `:"",p=r&&r.colors?_(r.colors):"";return` /* OverType Editor Styles */ /* Middle-ground CSS Reset - Prevent parent styles from leaking in */ @@ -62,9 +62,9 @@ var OverType=(()=>{var O=Object.defineProperty;var Fe=Object.getOwnPropertyDescr overflow: visible !important; /* Allow dropdown to overflow container */ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important; text-align: left !important; - ${c?` + ${p?` /* Theme Variables */ - ${c}`:""} + ${p}`:""} } /* Force left alignment for all elements in the editor */ @@ -861,28 +861,28 @@ var OverType=(()=>{var O=Object.defineProperty;var Fe=Object.getOwnPropertyDescr } ${a} - `}var Ke=Object.defineProperty,oe=Object.getOwnPropertySymbols,Ge=Object.prototype.hasOwnProperty,Ze=Object.prototype.propertyIsEnumerable,ie=(o,e,t)=>e in o?Ke(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,re=(o,e)=>{for(var t in e||(e={}))Ge.call(e,t)&&ie(o,t,e[t]);if(oe)for(var t of oe(e))Ze.call(e,t)&&ie(o,t,e[t]);return o},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Je(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return re(re({},Je()),o)}var q=!1;function Qe(){return q}function b(o,e,t){q&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function R(o,e){if(!q)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function ce(o){q&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function P(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Qe();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),c=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(c.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` -`).length,"lines")}catch(p){H=!1,i&&console.log("execCommand threw error:",p)}o.contentEditable="false"}if(i&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let p=a+e+c,h=o.value;i&&(console.log("Expected length:",p.length),console.log("Actual length:",h.length)),h!==p&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(p.slice(0,100))),console.log("Actual:",JSON.stringify(h.slice(0,100))))}if(!H)if(i&&console.log("Using manual insertion"),o.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(p){}o.value=a+e+c;try{document.execCommand("ms-endUndoUnit")}catch(p){}o.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,n),t!=null&&n!=null?o.setSelectionRange(t,n):o.setSelectionRange(r,o.selectionEnd),i&&(console.log("Final value length:",o.value.length),console.groupEnd())}function se(o){return o.trim().split(` + `}var Ke=Object.defineProperty,oe=Object.getOwnPropertySymbols,Ge=Object.prototype.hasOwnProperty,Ze=Object.prototype.propertyIsEnumerable,ie=(o,e,t)=>e in o?Ke(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,re=(o,e)=>{for(var t in e||(e={}))Ge.call(e,t)&&ie(o,t,e[t]);if(oe)for(var t of oe(e))Ze.call(e,t)&&ie(o,t,e[t]);return o},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Je(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return re(re({},Je()),o)}var q=!1;function Qe(){return q}function b(o,e,t){q&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function R(o,e){if(!q)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function ce(o){q&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function P(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Qe();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),p=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(p.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` +`).length,"lines")}catch(c){H=!1,i&&console.log("execCommand threw error:",c)}o.contentEditable="false"}if(i&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let c=a+e+p,u=o.value;i&&(console.log("Expected length:",c.length),console.log("Actual length:",u.length)),u!==c&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(c.slice(0,100))),console.log("Actual:",JSON.stringify(u.slice(0,100))))}if(!H)if(i&&console.log("Using manual insertion"),o.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(c){}o.value=a+e+p;try{document.execCommand("ms-endUndoUnit")}catch(c){}o.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,n),t!=null&&n!=null?o.setSelectionRange(t,n):o.setSelectionRange(r,o.selectionEnd),i&&(console.log("Final value length:",o.value.length),console.groupEnd())}function se(o){return o.trim().split(` `).length>1}function Xe(o,e){let t=e;for(;o[t]&&o[t-1]!=null&&!o[t-1].match(/\s/);)t--;return t}function Ye(o,e,t){let n=e,i=t?/\n/:/\s/;for(;o[n]&&!o[n].match(i);)n++;return n}function pe(o){let e=o.value.split(` -`),t=0;for(let n=0;n=t&&o.selectionStart=t&&o.selectionEnd0&&s[a-1]!==` +`),t=0;for(let n=0;n=t&&o.selectionStart=t&&o.selectionEnd0&&s[a-1]!==` `;)a--;if(r){let d=n;for(;d0?`${s} +`;)d++;o.selectionStart=a,o.selectionEnd=d}else pe(o);let p=e(o);if(t.adjustSelection){let l=o.value.slice(o.selectionStart,o.selectionEnd).startsWith(t.prefix),c=t.adjustSelection(l,n,i,a);p.selectionStart=c.start,p.selectionEnd=c.end}else if(t.prefix){let l=o.value.slice(o.selectionStart,o.selectionEnd).startsWith(t.prefix);r?l?(p.selectionStart=Math.max(n-t.prefix.length,a),p.selectionEnd=p.selectionStart):(p.selectionStart=n+t.prefix.length,p.selectionEnd=p.selectionStart):l?(p.selectionStart=Math.max(n-t.prefix.length,a),p.selectionEnd=Math.max(i-t.prefix.length,a)):(p.selectionStart=n+t.prefix.length,p.selectionEnd=i+t.prefix.length)}return p}function U(o,e){let t,n,{prefix:i,suffix:r,blockPrefix:s,blockSuffix:a,replaceNext:p,prefixSpace:d,scanFor:l,surroundWithNewlines:c,trimFirst:u}=e,m=o.selectionStart,g=o.selectionEnd,f=o.value.slice(o.selectionStart,o.selectionEnd),v=se(f)&&s&&s.length>0?`${s} `:i,y=se(f)&&a&&a.length>0?` -${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(v=` ${v}`)}f=et(o,v,y,e.multiline);let w=o.selectionStart,x=o.selectionEnd,B=c&&c.length>0&&y.indexOf(c)>-1&&f.length>0;if(p){let L=Z(o);t=L.newlinesToAppend,n=L.newlinesToPrepend,v=t+i,y+=n}if(f.startsWith(v)&&f.endsWith(y)){let L=f.slice(v.length,f.length-y.length);if(m===g){let C=m-v.length;C=Math.max(C,w),C=Math.min(C,w+L.length),w=x=C}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if(B)if(l&&l.length>0&&f.match(l)){y=y.replace(c,f);let L=v+y;return w=x=w+v.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;return w=w+v.length+f.length+y.indexOf(c),x=w+c.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;w=m+v.length,x=g+v.length;let C=f.match(/^\s*|\s*$/g);if(h&&C){let X=C[0]||"",Y=C[1]||"";L=X+v+f.trim()+y+Y,w+=X.length,x-=Y.length}return{text:L,selectionStart:w,selectionEnd:x}}}function de(o,e){let{prefix:t,suffix:n,surroundWithNewlines:i}=e,r=o.value.slice(o.selectionStart,o.selectionEnd),s=o.selectionStart,a=o.selectionEnd,c=r.split(` -`);if(c.every(l=>l.startsWith(t)&&(!n||l.endsWith(n))))r=c.map(l=>{let p=l.slice(t.length);return n&&(p=p.slice(0,p.length-n.length)),p}).join(` -`),a=s+r.length;else if(r=c.map(l=>t+l+(n||"")).join(` -`),i){let{newlinesToAppend:l,newlinesToPrepend:p}=Z(o);s+=l.length,a=s+r.length,r=l+r+p}return{text:r,selectionStart:s,selectionEnd:a}}function ae(o){let e=o.split(` +${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&!L.match(/\s/)&&(v=` ${v}`)}f=et(o,v,y,e.multiline);let w=o.selectionStart,x=o.selectionEnd,B=p&&p.length>0&&y.indexOf(p)>-1&&f.length>0;if(c){let L=Z(o);t=L.newlinesToAppend,n=L.newlinesToPrepend,v=t+i,y+=n}if(f.startsWith(v)&&f.endsWith(y)){let L=f.slice(v.length,f.length-y.length);if(m===g){let C=m-v.length;C=Math.max(C,w),C=Math.min(C,w+L.length),w=x=C}else x=w+L.length;return{text:L,selectionStart:w,selectionEnd:x}}else if(B)if(l&&l.length>0&&f.match(l)){y=y.replace(p,f);let L=v+y;return w=x=w+v.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;return w=w+v.length+f.length+y.indexOf(p),x=w+p.length,{text:L,selectionStart:w,selectionEnd:x}}else{let L=v+f+y;w=m+v.length,x=g+v.length;let C=f.match(/^\s*|\s*$/g);if(u&&C){let X=C[0]||"",Y=C[1]||"";L=X+v+f.trim()+y+Y,w+=X.length,x-=Y.length}return{text:L,selectionStart:w,selectionEnd:x}}}function de(o,e){let{prefix:t,suffix:n,surroundWithNewlines:i}=e,r=o.value.slice(o.selectionStart,o.selectionEnd),s=o.selectionStart,a=o.selectionEnd,p=r.split(` +`);if(p.every(l=>l.startsWith(t)&&(!n||l.endsWith(n))))r=p.map(l=>{let c=l.slice(t.length);return n&&(c=c.slice(0,c.length-n.length)),c}).join(` +`),a=s+r.length;else if(r=p.map(l=>t+l+(n||"")).join(` +`),i){let{newlinesToAppend:l,newlinesToPrepend:c}=Z(o);s+=l.length,a=s+r.length,r=l+r+c}return{text:r,selectionStart:s,selectionEnd:a}}function ae(o){let e=o.split(` `),t=/^\d+\.\s+/,n=e.every(r=>t.test(r)),i=e;return n&&(i=e.map(r=>r.replace(t,""))),{text:i.join(` `),processed:n}}function le(o){let e=o.split(` `),t="- ",n=e.every(r=>r.startsWith(t)),i=e;return n&&(i=e.map(r=>r.slice(t.length))),{text:i.join(` -`),processed:n}}function F(o,e){return e?"- ":`${o+1}. `}function tt(o,e){let t,n,i;return o.orderedList?(t=ae(e),n=le(t.text),i=n.text):(t=le(e),n=ae(t.text),i=n.text),[t,n,i]}function nt(o,e){let t=o.selectionStart===o.selectionEnd,n=o.selectionStart,i=o.selectionEnd;pe(o);let r=o.value.slice(o.selectionStart,o.selectionEnd),[s,a,c]=tt(e,r),d=c.split(` -`).map((f,v)=>`${F(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+F(y,e.unorderedList).length,0),p=d.reduce((f,v,y)=>f+F(y,!e.unorderedList).length,0);if(s.processed)return t?(n=Math.max(n-F(0,e.unorderedList).length,0),i=n):(n=o.selectionStart,i=o.selectionEnd-l),{text:c,selectionStart:n,selectionEnd:i};let{newlinesToAppend:h,newlinesToPrepend:m}=Z(o),g=h+d.join(` -`)+m;return t?(n=Math.max(n+F(0,e.unorderedList).length+h.length,0),i=n):a.processed?(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l-p):(n=Math.max(o.selectionStart+h.length,0),i=o.selectionEnd+h.length+l),{text:g,selectionStart:n,selectionEnd:i}}function ue(o,e){let t=V(o,n=>nt(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),c=/^\d+\.\s+/,d=/^- /,l=c.test(a),p=d.test(a),h=e.orderedList&&l||e.unorderedList&&p;if(i===r)if(h){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(i-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:i+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:i+m}}else if(h){let m=a.match(e.orderedList?c:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(r-g,s)}}else if(l||p){let m=a.match(l?c:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:r+m}}}});P(o,t)}function ot(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` -`),s=0,a="";for(let p of r){if(t>=s&&t<=s+p.length){a=p;break}s+=p.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let c=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(c,d);if(l.includes("**")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("**"),g=h.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("_"),g=h.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100));p.includes("`")&&h.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let p=i.slice(Math.max(0,t-100),t),h=i.slice(n,Math.min(i.length,n+100)),m=p.lastIndexOf("["),g=h.indexOf("]");m!==-1&&g!==-1&&i.slice(n+g+1,n+g+10).startsWith("(")&&e.push("link")}return e}function he(o){if(!o||o.disabled||o.readOnly)return;b("toggleBold","Starting"),R(o,"Before");let e=$(T.bold),t=U(o,e);ce(t),P(o,t),R(o,"After")}function me(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.italic),t=U(o,e);P(o,t)}function fe(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.code),t=U(o,e);P(o,t)}function ge(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=$(T.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);P(o,r)}function ve(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.bulletList);ue(o,e)}function ye(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.numberedList);ue(o,e)}function be(o){if(!o||o.disabled||o.readOnly)return;b("toggleQuote","Starting"),R(o,"Initial");let e=$(T.quote),t=V(o,n=>de(n,e),{prefix:e.prefix});ce(t),P(o,t),R(o,"Final")}function J(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.taskList),t=V(o,n=>de(n,e),{prefix:e.prefix});P(o,t)}function Q(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=$(T[n]||T.header1);b("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,c=s;for(;c>0&&r[c-1]!==` -`;)c--;let d=a;for(;d{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):h>0?(b("insertHeader",`ACTION: Replacing H${h} with H${e}`),x=i.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=i.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:i.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let B=Math.max(y-m,x);return b("insertHeader",` - Removing header, adjusting by -${m}`),{start:B,end:y===w?B:Math.max(w-m,x)}}else if(m>0){let B=i.prefix.length-m;return b("insertHeader",` - Replacing header, adjusting by ${B}`),{start:y+B,end:w+B}}else return b("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:y+i.prefix.length,end:w+i.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),P(o,f)}function we(o){Q(o,1,!0)}function xe(o){Q(o,2,!0)}function ke(o){Q(o,3,!0)}function Le(o){return ot(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Le)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` +`),processed:n}}function F(o,e){return e?"- ":`${o+1}. `}function tt(o,e){let t,n,i;return o.orderedList?(t=ae(e),n=le(t.text),i=n.text):(t=le(e),n=ae(t.text),i=n.text),[t,n,i]}function nt(o,e){let t=o.selectionStart===o.selectionEnd,n=o.selectionStart,i=o.selectionEnd;pe(o);let r=o.value.slice(o.selectionStart,o.selectionEnd),[s,a,p]=tt(e,r),d=p.split(` +`).map((f,v)=>`${F(v,e.unorderedList)}${f}`),l=d.reduce((f,v,y)=>f+F(y,e.unorderedList).length,0),c=d.reduce((f,v,y)=>f+F(y,!e.unorderedList).length,0);if(s.processed)return t?(n=Math.max(n-F(0,e.unorderedList).length,0),i=n):(n=o.selectionStart,i=o.selectionEnd-l),{text:p,selectionStart:n,selectionEnd:i};let{newlinesToAppend:u,newlinesToPrepend:m}=Z(o),g=u+d.join(` +`)+m;return t?(n=Math.max(n+F(0,e.unorderedList).length+u.length,0),i=n):a.processed?(n=Math.max(o.selectionStart+u.length,0),i=o.selectionEnd+u.length+l-c):(n=Math.max(o.selectionStart+u.length,0),i=o.selectionEnd+u.length+l),{text:g,selectionStart:n,selectionEnd:i}}function he(o,e){let t=V(o,n=>nt(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),p=/^\d+\.\s+/,d=/^- /,l=p.test(a),c=d.test(a),u=e.orderedList&&l||e.unorderedList&&c;if(i===r)if(u){let m=a.match(e.orderedList?p:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(i-g,s)}}else if(l||c){let m=a.match(l?p:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:i+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:i+m}}else if(u){let m=a.match(e.orderedList?p:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(r-g,s)}}else if(l||c){let m=a.match(l?p:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:r+m}}}});P(o,t)}function ot(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` +`),s=0,a="";for(let c of r){if(t>=s&&t<=s+c.length){a=c;break}s+=c.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let p=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(p,d);if(l.includes("**")){let c=i.slice(Math.max(0,t-100),t),u=i.slice(n,Math.min(i.length,n+100)),m=c.lastIndexOf("**"),g=u.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let c=i.slice(Math.max(0,t-100),t),u=i.slice(n,Math.min(i.length,n+100)),m=c.lastIndexOf("_"),g=u.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let c=i.slice(Math.max(0,t-100),t),u=i.slice(n,Math.min(i.length,n+100));c.includes("`")&&u.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let c=i.slice(Math.max(0,t-100),t),u=i.slice(n,Math.min(i.length,n+100)),m=c.lastIndexOf("["),g=u.indexOf("]");m!==-1&&g!==-1&&i.slice(n+g+1,n+g+10).startsWith("(")&&e.push("link")}return e}function ue(o){if(!o||o.disabled||o.readOnly)return;b("toggleBold","Starting"),R(o,"Before");let e=$(T.bold),t=U(o,e);ce(t),P(o,t),R(o,"After")}function me(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.italic),t=U(o,e);P(o,t)}function fe(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.code),t=U(o,e);P(o,t)}function ge(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=$(T.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);P(o,r)}function ve(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.bulletList);he(o,e)}function ye(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.numberedList);he(o,e)}function be(o){if(!o||o.disabled||o.readOnly)return;b("toggleQuote","Starting"),R(o,"Initial");let e=$(T.quote),t=V(o,n=>de(n,e),{prefix:e.prefix});ce(t),P(o,t),R(o,"Final")}function J(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.taskList),t=V(o,n=>de(n,e),{prefix:e.prefix});P(o,t)}function Q(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=$(T[n]||T.header1);b("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,p=s;for(;p>0&&r[p-1]!==` +`;)p--;let d=a;for(;d{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):u>0?(b("insertHeader",`ACTION: Replacing H${u} with H${e}`),x=i.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=i.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:i.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let B=Math.max(y-m,x);return b("insertHeader",` - Removing header, adjusting by -${m}`),{start:B,end:y===w?B:Math.max(w-m,x)}}else if(m>0){let B=i.prefix.length-m;return b("insertHeader",` - Replacing header, adjusting by ${B}`),{start:y+B,end:w+B}}else return b("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:y+i.prefix.length,end:w+i.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),P(o,f)}function we(o){Q(o,1,!0)}function xe(o){Q(o,2,!0)}function ke(o){Q(o,3,!0)}function Le(o){return ot(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Le)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` @@ -939,24 +939,24 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! `,Ne=` -`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Ee,title:"Bold (Ctrl+B)",action:({editor:o})=>{he(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:$e,title:"Inline Code",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ce,title:"Heading 1",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Me,title:"Heading 3",action:({editor:o})=>{ke(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:Ie,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Be,title:"Numbered List",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:_e,title:"Task List",action:({editor:o})=>{J&&(J(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function ze(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function je(o){let e=o||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function rt(o,e){let t=je(o),n=je(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(u.prototype);return s._init(r,t),r.overTypeInstance=s,u.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++u.instanceCount,this.initialized=!1,u.injectStyles(),u.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||u.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=_(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||u.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=_(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=ze(N),this.options.toolbarButtons&&Object.assign(this.actionsById,ze(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tp.replace(/^ /,"")).join(` -`);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else if(n!==i){let s=r.substring(0,n),a=r.substring(n,i),c=r.substring(i),l=a.split(` -`).map(p=>" "+p).join(` -`);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+c,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else document.execCommand?document.execCommand("insertText",!1," "):(this.textarea.value=r.substring(0,n)+" "+r.substring(i),this.textarea.selectionStart=this.textarea.selectionEnd=n+2);this.textarea.dispatchEvent(new Event("input",{bubbles:!0}));return}if(e.key==="Enter"&&!e.shiftKey&&!e.metaKey&&!e.ctrlKey&&this.options.smartLists&&this.handleSmartListContinuation()){e.preventDefault();return}!this.shortcuts.handleKeydown(e)&&this.options.onKeydown&&this.options.onKeydown(e,this)}handleSmartListContinuation(){let e=this.textarea,t=e.selectionStart,n=S.getListContext(e.value,t);return!n||!n.inList?!1:n.content.trim()===""&&t>=n.markerEndPos?(this.deleteListMarker(n),!0):(t>n.markerEndPos&&t`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Ee,title:"Bold (Ctrl+B)",action:({editor:o})=>{ue(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:$e,title:"Inline Code",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ce,title:"Heading 1",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Me,title:"Heading 3",action:({editor:o})=>{ke(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:Ie,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Be,title:"Numbered List",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:_e,title:"Task List",action:({editor:o})=>{J&&(J(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function ze(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function je(o){let e=o||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function rt(o,e){let t=je(o),n=je(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(h.prototype);return s._init(r,t),r.overTypeInstance=s,h.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++h.instanceCount,this.initialized=!1,h.injectStyles(),h.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||h.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=_(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||h.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=_(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=ze(N),this.options.toolbarButtons&&Object.assign(this.actionsById,ze(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tc.replace(/^ /,"")).join(` +`);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+p,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else if(n!==i){let s=r.substring(0,n),a=r.substring(n,i),p=r.substring(i),l=a.split(` +`).map(c=>" "+c).join(` +`);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+p,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else document.execCommand?document.execCommand("insertText",!1," "):(this.textarea.value=r.substring(0,n)+" "+r.substring(i),this.textarea.selectionStart=this.textarea.selectionEnd=n+2);this.textarea.dispatchEvent(new Event("input",{bubbles:!0}));return}if(e.key==="Enter"&&!e.shiftKey&&!e.metaKey&&!e.ctrlKey&&this.options.smartLists&&this.handleSmartListContinuation()){e.preventDefault();return}!this.shortcuts.handleKeydown(e)&&this.options.onKeydown&&this.options.onKeydown(e,this)}handleSmartListContinuation(){let e=this.textarea,t=e.selectionStart,n=S.getListContext(e.value,t);return!n||!n.inList?!1:n.content.trim()===""&&t>=n.markerEndPos?(this.deleteListMarker(n),!0):(t>n.markerEndPos&&t{this.updateNumberedLists()},10)}updateNumberedLists(){let e=this.textarea.value,t=this.textarea.selectionStart,n=S.renumberLists(e);if(n!==e){let i=0,r=e.split(` `),s=n.split(` -`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&rt(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(K("auto"));else{let t=typeof e=="string"?M(e):e,n=t.name||e;n&&this.container.setAttribute("data-theme",n),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}return this}_applyTheme(e){let t=M(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}_setupAuto(){var e;window.matchMedia&&(u._autoInstances.add(this),u._mq||(u._mq=window.matchMedia("(prefers-color-scheme: dark)"),u._mqListener=t=>{let n=t.matches?"cave":"solar";u._autoInstances.forEach(i=>i._applyTheme(n))},(e=u._mq.addEventListener||u._mq.addListener)==null||e.call(u._mq,"change",u._mqListener)))}_cleanupAuto(){var e;u._autoInstances.delete(this),u._autoInstances.size===0&&u._mq&&((e=u._mq.removeEventListener||u._mq.removeListener)==null||e.call(u._mq,"change",u._mqListener),u._mq=null,u._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` +`),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&rt(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(K("auto"));else{let t=typeof e=="string"?M(e):e,n=t.name||e;n&&this.container.setAttribute("data-theme",n),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}return this}_applyTheme(e){let t=M(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}_setupAuto(){var e;window.matchMedia&&(h._autoInstances.add(this),h._mq||(h._mq=window.matchMedia("(prefers-color-scheme: dark)"),h._mqListener=t=>{let n=t.matches?"cave":"solar";h._autoInstances.forEach(i=>i._applyTheme(n))},(e=h._mq.addEventListener||h._mq.addListener)==null||e.call(h._mq,"change",h._mqListener)))}_cleanupAuto(){var e;h._autoInstances.delete(this),h._autoInstances.size===0&&h._mq&&((e=h._mq.removeEventListener||h._mq.removeListener)==null||e.call(h._mq,"change",h._mqListener),h._mq=null,h._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` `),n=e.length,i=e.split(/\s+/).filter(l=>l.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(` -`),c=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:n,words:i,lines:t.length,line:c,column:d}):this.statsBar.innerHTML=` +`),p=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:n,words:i,lines:t.length,line:p,column:d}):this.statsBar.innerHTML=`
    ${n} chars, ${i} words, ${t.length} lines
    -
    Line ${c}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let c=e.scrollHeight;if(this.options.minHeight){let p=parseInt(this.options.minHeight);c=Math.max(c,p)}let d="hidden";if(this.options.maxHeight){let p=parseInt(this.options.maxHeight);c>p&&(c=p,d="auto")}let l=c+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==c&&(this.previousHeight=c)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,u.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new u(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let c=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[c]=u._parseDataValue(s.value)}return new u(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||u.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=u.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(u.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=u.currentTheme||A,i=ne({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),u.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let n=document.querySelectorAll(".overtype-container"),i=document.querySelectorAll(".overtype-wrapper");n.forEach(r=>{t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)}),i.forEach(r=>{var s;r.closest(".overtype-container")||(t?(r.setAttribute("data-theme","auto"),r.setAttribute("data-resolved-theme",e)):r.setAttribute("data-theme",e)),(s=r._instance)==null||s.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(r=>{var s,a,c,d;t?((s=r.setAttribute)==null||s.call(r,"theme","auto"),(a=r.setAttribute)==null||a.call(r,"data-resolved-theme",e)):(c=r.setAttribute)==null||c.call(r,"theme",e),(d=r.refreshTheme)==null||d.call(r)})}static setTheme(e,t=null){if(u._cleanupGlobalAuto(),e==="auto")u._setupGlobalAuto(),u._applyGlobalTheme(K("auto"),t,!0);else{let n=typeof e=="string"?M(e):e;t&&(n=G(n,t)),u.currentTheme=n,u.injectStyles(!0);let i=n.name||e;i&&u._updateThemeAttrs(i)}}static _applyGlobalTheme(e,t=null,n=!1){let i=M(e);t&&(i=G(i,t)),u.currentTheme=i,u.injectStyles(!0),u._updateThemeAttrs(e,n)}static _setupGlobalAuto(){var e;!window.matchMedia||u._globalAutoMq||(u._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),u._globalAutoListener=t=>{u._applyGlobalTheme(t.matches?"cave":"solar",null,!0)},(e=u._globalAutoMq.addEventListener||u._globalAutoMq.addListener)==null||e.call(u._globalAutoMq,"change",u._globalAutoListener))}static _cleanupGlobalAuto(){var e;u._globalAutoMq&&u._globalAutoListener&&((e=u._globalAutoMq.removeEventListener||u._globalAutoMq.removeListener)==null||e.call(u._globalAutoMq,"change",u._globalAutoListener),u._globalAutoMq=null,u._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){u.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),u.globalListenersInitialized=!0)}};E(u,"instances",new WeakMap),E(u,"stylesInjected",!1),E(u,"globalListenersInitialized",!1),E(u,"instanceCount",0),E(u,"_mq",null),E(u,"_mqListener",null),E(u,"_autoInstances",new Set),E(u,"_globalAutoMq",null),E(u,"_globalAutoListener",null);var I=u;I.MarkdownParser=S;I.ShortcutsManager=z;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var st=I;return De(at);})(); +
    Line ${p}, Col ${d}
    + `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let p=e.scrollHeight;if(this.options.minHeight){let c=parseInt(this.options.minHeight);p=Math.max(p,c)}let d="hidden";if(this.options.maxHeight){let c=parseInt(this.options.maxHeight);p>c&&(p=c,d="auto")}let l=p+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==p&&(this.previousHeight=p)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,h.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new h(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let p=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[p]=h._parseDataValue(s.value)}return new h(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||h.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=h.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(h.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=h.currentTheme||A,i=ne({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),h.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let n=i=>{t?(i.setAttribute("data-theme","auto"),i.setAttribute("data-resolved-theme",e)):i.setAttribute("data-theme",e)};document.querySelectorAll(".overtype-container").forEach(n),document.querySelectorAll(".overtype-wrapper").forEach(i=>{var r;i.closest(".overtype-container")||n(i),(r=i._instance)==null||r.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(i=>{var r,s,a;(r=i.setAttribute)==null||r.call(i,"theme",t?"auto":e),t&&((s=i.setAttribute)==null||s.call(i,"data-resolved-theme",e)),(a=i.refreshTheme)==null||a.call(i)})}static setTheme(e,t=null){if(h._cleanupGlobalAuto(),e==="auto")h._setupGlobalAuto(),h._applyGlobalTheme(K("auto"),t,!0);else{let n=typeof e=="string"?M(e):e;t&&(n=G(n,t)),h.currentTheme=n,h.injectStyles(!0);let i=n.name||e;i&&h._updateThemeAttrs(i)}}static _applyGlobalTheme(e,t=null,n=!1){let i=M(e);t&&(i=G(i,t)),h.currentTheme=i,h.injectStyles(!0),h._updateThemeAttrs(e,n)}static _setupGlobalAuto(){var e;!window.matchMedia||h._globalAutoMq||(h._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),h._globalAutoListener=t=>{h._applyGlobalTheme(t.matches?"cave":"solar",null,!0)},(e=h._globalAutoMq.addEventListener||h._globalAutoMq.addListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener))}static _cleanupGlobalAuto(){var e;h._globalAutoMq&&h._globalAutoListener&&((e=h._globalAutoMq.removeEventListener||h._globalAutoMq.removeListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener),h._globalAutoMq=null,h._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){h.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),h.globalListenersInitialized=!0)}};E(h,"instances",new WeakMap),E(h,"stylesInjected",!1),E(h,"globalListenersInitialized",!1),E(h,"instanceCount",0),E(h,"_mq",null),E(h,"_mqListener",null),E(h,"_autoInstances",new Set),E(h,"_globalAutoMq",null),E(h,"_globalAutoListener",null);var I=h;I.MarkdownParser=S;I.ShortcutsManager=z;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var st=I;return De(at);})(); /** * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment * @version 1.0.0 diff --git a/src/overtype.js b/src/overtype.js index 42d117f..d4a4536 100644 --- a/src/overtype.js +++ b/src/overtype.js @@ -1447,39 +1447,25 @@ class OverType { * @private */ static _updateThemeAttrs(themeName, isAuto = false) { - // Single query for containers and wrappers - const containers = document.querySelectorAll('.overtype-container'); - const wrappers = document.querySelectorAll('.overtype-wrapper'); - - containers.forEach(el => { + const setTheme = (el) => { if (isAuto) { el.setAttribute('data-theme', 'auto'); el.setAttribute('data-resolved-theme', themeName); } else { el.setAttribute('data-theme', themeName); } - }); + }; - wrappers.forEach(wrapper => { - if (!wrapper.closest('.overtype-container')) { - if (isAuto) { - wrapper.setAttribute('data-theme', 'auto'); - wrapper.setAttribute('data-resolved-theme', themeName); - } else { - wrapper.setAttribute('data-theme', themeName); - } - } - wrapper._instance?.updatePreview(); + document.querySelectorAll('.overtype-container').forEach(setTheme); + + document.querySelectorAll('.overtype-wrapper').forEach(w => { + if (!w.closest('.overtype-container')) setTheme(w); + w._instance?.updatePreview(); }); - // Update web components document.querySelectorAll('overtype-editor').forEach(wc => { - if (isAuto) { - wc.setAttribute?.('theme', 'auto'); - wc.setAttribute?.('data-resolved-theme', themeName); - } else { - wc.setAttribute?.('theme', themeName); - } + wc.setAttribute?.(isAuto ? 'theme' : 'theme', isAuto ? 'auto' : themeName); + if (isAuto) wc.setAttribute?.('data-resolved-theme', themeName); wc.refreshTheme?.(); }); } From 451e957115447ddf3e4c8730831ddc6f0374ae94 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 13 Feb 2026 15:30:42 +0000 Subject: [PATCH 7/8] Fix web component setAttribute call and add clarifying comments Co-authored-by: dido739 <152557154+dido739@users.noreply.github.com> --- dist/overtype-webcomponent.esm.js | 14 ++++++++------ dist/overtype-webcomponent.js | 14 ++++++++------ dist/overtype.cjs | 14 ++++++++------ dist/overtype.esm.js | 14 ++++++++------ dist/overtype.esm.js.map | 4 ++-- dist/overtype.js | 14 ++++++++------ dist/overtype.js.map | 4 ++-- src/overtype.js | 14 ++++++++------ 8 files changed, 52 insertions(+), 40 deletions(-) diff --git a/dist/overtype-webcomponent.esm.js b/dist/overtype-webcomponent.esm.js index 6574aa2..ac31ed1 100644 --- a/dist/overtype-webcomponent.esm.js +++ b/dist/overtype-webcomponent.esm.js @@ -3375,7 +3375,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { - // Global auto theme listener + // Listener for global auto theme /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4419,7 +4419,7 @@ var _OverType = class _OverType { }); document.querySelectorAll("overtype-editor").forEach((wc) => { var _a, _b, _c; - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", isAuto ? "auto" : themeName); if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); @@ -4599,14 +4599,16 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); +// Instance-level auto theme tracking (when individual instances use auto theme) __publicField(_OverType, "_mq", null); -// Shared media query for auto theme +// Shared media query for instance auto themes __publicField(_OverType, "_mqListener", null); -// Shared listener +// Shared listener for instance auto themes __publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); -// Track auto-themed instances +// Track instances using auto theme +// Global-level auto theme tracking (when OverType.setTheme('auto') is called) __publicField(_OverType, "_globalAutoMq", null); -// Global auto theme media query +// Media query for global auto theme __publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; diff --git a/dist/overtype-webcomponent.js b/dist/overtype-webcomponent.js index 1d237c8..8c4cb99 100644 --- a/dist/overtype-webcomponent.js +++ b/dist/overtype-webcomponent.js @@ -3398,7 +3398,7 @@ ${blockSuffix}` : suffix; return false; } var _OverType = class _OverType { - // Global auto theme listener + // Listener for global auto theme /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4442,7 +4442,7 @@ ${blockSuffix}` : suffix; }); document.querySelectorAll("overtype-editor").forEach((wc) => { var _a, _b, _c; - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", isAuto ? "auto" : themeName); if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); @@ -4622,14 +4622,16 @@ ${blockSuffix}` : suffix; __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); + // Instance-level auto theme tracking (when individual instances use auto theme) __publicField(_OverType, "_mq", null); - // Shared media query for auto theme + // Shared media query for instance auto themes __publicField(_OverType, "_mqListener", null); - // Shared listener + // Shared listener for instance auto themes __publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); - // Track auto-themed instances + // Track instances using auto theme + // Global-level auto theme tracking (when OverType.setTheme('auto') is called) __publicField(_OverType, "_globalAutoMq", null); - // Global auto theme media query + // Media query for global auto theme __publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; diff --git a/dist/overtype.cjs b/dist/overtype.cjs index 13dd0ac..b9873f9 100644 --- a/dist/overtype.cjs +++ b/dist/overtype.cjs @@ -3401,7 +3401,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { - // Global auto theme listener + // Listener for global auto theme /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4445,7 +4445,7 @@ var _OverType = class _OverType { }); document.querySelectorAll("overtype-editor").forEach((wc) => { var _a, _b, _c; - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", isAuto ? "auto" : themeName); if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); @@ -4625,14 +4625,16 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); +// Instance-level auto theme tracking (when individual instances use auto theme) __publicField(_OverType, "_mq", null); -// Shared media query for auto theme +// Shared media query for instance auto themes __publicField(_OverType, "_mqListener", null); -// Shared listener +// Shared listener for instance auto themes __publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); -// Track auto-themed instances +// Track instances using auto theme +// Global-level auto theme tracking (when OverType.setTheme('auto') is called) __publicField(_OverType, "_globalAutoMq", null); -// Global auto theme media query +// Media query for global auto theme __publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; diff --git a/dist/overtype.esm.js b/dist/overtype.esm.js index 1aeb788..3c8bf1f 100644 --- a/dist/overtype.esm.js +++ b/dist/overtype.esm.js @@ -3375,7 +3375,7 @@ function toolbarButtonsChanged(prevButtons, nextButtons) { return false; } var _OverType = class _OverType { - // Global auto theme listener + // Listener for global auto theme /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4419,7 +4419,7 @@ var _OverType = class _OverType { }); document.querySelectorAll("overtype-editor").forEach((wc) => { var _a, _b, _c; - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", isAuto ? "auto" : themeName); if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); @@ -4599,14 +4599,16 @@ __publicField(_OverType, "instances", /* @__PURE__ */ new WeakMap()); __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); +// Instance-level auto theme tracking (when individual instances use auto theme) __publicField(_OverType, "_mq", null); -// Shared media query for auto theme +// Shared media query for instance auto themes __publicField(_OverType, "_mqListener", null); -// Shared listener +// Shared listener for instance auto themes __publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); -// Track auto-themed instances +// Track instances using auto theme +// Global-level auto theme tracking (when OverType.setTheme('auto') is called) __publicField(_OverType, "_globalAutoMq", null); -// Global auto theme media query +// Media query for global auto theme __publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; diff --git a/dist/overtype.esm.js.map b/dist/overtype.esm.js.map index fc48e04..4a3de8a 100644 --- a/dist/overtype.esm.js.map +++ b/dist/overtype.esm.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js", "../src/overtype.js"], - "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `[${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n const setTheme = (el) => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n };\n \n document.querySelectorAll('.overtype-container').forEach(setTheme);\n \n document.querySelectorAll('.overtype-wrapper').forEach(w => {\n if (!w.closest('.overtype-container')) setTheme(w);\n w._instance?.updatePreview();\n });\n \n document.querySelectorAll('overtype-editor').forEach(wc => {\n wc.setAttribute?.(isAuto ? 'theme' : 'theme', isAuto ? 'auto' : themeName);\n if (isAuto) wc.setAttribute?.('data-resolved-theme', themeName);\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], - "mappings": ";;;;;;;;;;;;;;;AAQO,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA,EAa1B,OAAO,iBAAiB;AACtB,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,aAAa;AACrC,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,gBAAgB,WAAW;AAChC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,MAAM;AAC7B,QAAI,KAAK,cAAc;AACrB,aAAO,KAAK,aAAa,IAAI;AAAA,IAC/B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WAAW,MAAM;AACtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,WAAO,KAAK,QAAQ,YAAY,OAAK,IAAI,CAAC,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,oBAAoB,MAAM,cAAc;AAC7C,UAAM,gBAAgB,aAAa,MAAM,QAAQ,EAAE,CAAC;AACpD,UAAM,cAAc,cAAc,QAAQ,MAAM,QAAQ;AACxD,WAAO,KAAK,QAAQ,QAAQ,WAAW;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,MAAM;AACvB,WAAO,KAAK,QAAQ,oBAAoB,CAAC,OAAO,QAAQ,YAAY;AAClE,YAAM,QAAQ,OAAO;AACrB,aAAO,KAAK,KAAK,gCAAgC,MAAM,WAAW,OAAO,MAAM,KAAK;AAAA,IACtF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,oBAAoB,MAAM;AAC/B,QAAI,KAAK,MAAM,wBAAwB,GAAG;AACxC,aAAO,gCAAgC,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAC3B,WAAO,KAAK,QAAQ,eAAe,CAAC,OAAO,YAAY;AACrD,aAAO,oEAAoE,OAAO;AAAA,IACpF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAC3B,WAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,aAAO,GAAG,MAAM,uDAAuD,MAAM,WAAW,OAAO;AAAA,IACjG,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,cAAc,MAAM,gBAAgB,OAAO;AAChD,WAAO,KAAK,QAAQ,yCAAyC,CAAC,OAAO,QAAQ,SAAS,YAAY;AAChG,UAAI,eAAe;AAEjB,cAAM,YAAY,QAAQ,YAAY,MAAM;AAC5C,eAAO,GAAG,MAAM,gDAAgD,YAAY,YAAY,EAAE,KAAK,OAAO;AAAA,MACxG,OAAO;AAEL,eAAO,GAAG,MAAM,wDAAwD,OAAO,YAAY,OAAO;AAAA,MACpG;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,MAAM;AAC7B,WAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,aAAO,GAAG,MAAM,wDAAwD,MAAM,WAAW,OAAO;AAAA,IAClG,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,eAAe,MAAM;AAE1B,UAAM,iBAAiB;AACvB,QAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,aAAO,iCAAiC,IAAI;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAAM;AACrB,WAAO,KAAK,QAAQ,kBAAkB,+FAA+F;AACrI,WAAO,KAAK,QAAQ,cAAc,+FAA+F;AACjI,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,YAAY,MAAM;AAGvB,WAAO,KAAK,QAAQ,WAAC,gDAAuC,GAAC,GAAE,qFAAqF;AAIpJ,WAAO,KAAK,QAAQ,WAAC,8CAAyC,GAAC,GAAE,qFAAqF;AAEtJ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,mBAAmB,MAAM;AAE9B,WAAO,KAAK,QAAQ,WAAC,mCAAgC,GAAC,GAAE,yFAAyF;AAEjJ,WAAO,KAAK,QAAQ,WAAC,iCAA8B,GAAC,GAAE,uFAAuF;AAC7I,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAS3B,WAAO,KAAK,QAAQ,WAAC,6CAAwC,GAAC,GAAE,2FAA2F;AAAA,EAC7J;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,KAAK;AAEtB,UAAM,UAAU,IAAI,KAAK;AACzB,UAAM,QAAQ,QAAQ,YAAY;AAGlC,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,kBAAkB,cAAc,KAAK,cAAY,MAAM,WAAW,QAAQ,CAAC;AAGjF,UAAM,aAAa,QAAQ,WAAW,GAAG,KACvB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACrB,CAAC,QAAQ,SAAS,GAAG,KAAK,CAAC,QAAQ,SAAS,IAAI;AAGnE,QAAI,mBAAmB,YAAY;AACjC,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WAAW,MAAM;AACtB,WAAO,KAAK,QAAQ,uBAAuB,CAAC,OAAO,MAAM,QAAQ;AAC/D,YAAM,aAAa,UAAU,KAAK,WAAW;AAE7C,YAAM,UAAU,KAAK,YAAY,GAAG;AAEpC,aAAO,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,IAAI,0CAA0C,GAAG;AAAA,IACzJ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,8BAA8B,MAAM;AACzC,UAAM,cAAc,oBAAI,IAAI;AAC5B,QAAI,mBAAmB;AACvB,QAAI,gBAAgB;AAGpB,UAAM,mBAAmB,CAAC;AAG1B,UAAM,YAAY;AAClB,QAAI;AACJ,YAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAIlD,YAAM,aAAa,UAAU,QAAQ,UAAU,CAAC,EAAE,QAAQ,IAAI;AAC9D,YAAM,WAAW,aAAa;AAC9B,YAAM,SAAS,WAAW,UAAU,CAAC,EAAE;AACvC,uBAAiB,KAAK,EAAE,OAAO,UAAU,KAAK,OAAO,CAAC;AAAA,IACxD;AAGA,UAAM,YAAY,WAAC,6CAAwC,GAAC;AAC5D,QAAI;AACJ,UAAM,cAAc,CAAC;AAErB,YAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAClD,YAAM,YAAY,UAAU;AAC5B,YAAM,UAAU,UAAU,QAAQ,UAAU,CAAC,EAAE;AAG/C,YAAM,oBAAoB,iBAAiB;AAAA,QAAK,YAC9C,aAAa,OAAO,SAAS,WAAW,OAAO;AAAA,MACjD;AAEA,UAAI,CAAC,mBAAmB;AACtB,oBAAY,KAAK;AAAA,UACf,OAAO,UAAU,CAAC;AAAA,UAClB,OAAO,UAAU;AAAA,UACjB,WAAW,UAAU,CAAC;AAAA,UACtB,SAAS,UAAU,CAAC;AAAA,UACpB,YAAY,UAAU,CAAC;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF;AAGA,gBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC5C,gBAAY,QAAQ,cAAY;AAC9B,YAAM,cAAc,SAAS,kBAAkB;AAC/C,kBAAY,IAAI,aAAa;AAAA,QAC3B,MAAM;AAAA,QACN,UAAU,SAAS;AAAA,QACnB,WAAW,SAAS;AAAA,QACpB,SAAS,SAAS;AAAA,QAClB,YAAY,SAAS;AAAA,MACvB,CAAC;AACD,sBAAgB,cAAc,UAAU,GAAG,SAAS,KAAK,IAC1C,cACA,cAAc,UAAU,SAAS,QAAQ,SAAS,MAAM,MAAM;AAAA,IAC/E,CAAC;AAGD,oBAAgB,cAAc,QAAQ,4BAA4B,CAAC,OAAO,UAAU,QAAQ;AAC1F,YAAM,cAAc,SAAS,kBAAkB;AAC/C,kBAAY,IAAI,aAAa;AAAA,QAC3B,MAAM;AAAA,QACN,UAAU;AAAA,QACV;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAED,WAAO,EAAE,eAAe,YAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,+BAA+B,MAAM,aAAa;AAEvD,UAAM,eAAe,MAAM,KAAK,YAAY,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACjE,YAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,YAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,iBAAa,QAAQ,iBAAe;AAClC,YAAM,YAAY,YAAY,IAAI,WAAW;AAC7C,UAAI;AAEJ,UAAI,UAAU,SAAS,QAAQ;AAE7B,sBAAc,qCAAqC,UAAU,SAAS,UAAU,UAAU,OAAO,+BAA+B,UAAU,UAAU;AAAA,MACtJ,WAAW,UAAU,SAAS,QAAQ;AAEpC,YAAI,oBAAoB,UAAU;AAIlC,oBAAY,QAAQ,CAAC,gBAAgB,qBAAqB;AACxD,cAAI,kBAAkB,SAAS,gBAAgB,GAAG;AAChD,gBAAI,eAAe,SAAS,QAAQ;AAClC,oBAAM,WAAW,qCAAqC,eAAe,SAAS,UAAU,eAAe,OAAO,+BAA+B,eAAe,UAAU;AACtK,kCAAoB,kBAAkB,QAAQ,kBAAkB,QAAQ;AAAA,YAC1E;AAAA,UACF;AAAA,QACF,CAAC;AAGD,4BAAoB,KAAK,mBAAmB,iBAAiB;AAC7D,4BAAoB,KAAK,UAAU,iBAAiB;AACpD,4BAAoB,KAAK,YAAY,iBAAiB;AAItD,cAAM,aAAa,UAAU,KAAK,WAAW;AAC7C,cAAM,UAAU,KAAK,YAAY,UAAU,GAAG;AAC9C,sBAAc,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,iBAAiB,0CAA0C,UAAU,GAAG;AAAA,MACvL;AAEA,aAAO,KAAK,QAAQ,aAAa,WAAW;AAAA,IAC9C,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,oBAAoB,MAAM;AAE/B,UAAM,EAAE,eAAe,YAAY,IAAI,KAAK,8BAA8B,IAAI;AAG9E,QAAI,OAAO;AACX,WAAO,KAAK,mBAAmB,IAAI;AACnC,WAAO,KAAK,UAAU,IAAI;AAC1B,WAAO,KAAK,YAAY,IAAI;AAG5B,WAAO,KAAK,+BAA+B,MAAM,WAAW;AAE5D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAAM,gBAAgB,OAAO;AAC5C,QAAI,OAAO,KAAK,WAAW,IAAI;AAG/B,WAAO,KAAK,oBAAoB,MAAM,IAAI;AAG1C,UAAM,iBAAiB,KAAK,oBAAoB,IAAI;AACpD,QAAI;AAAgB,aAAO;AAE3B,UAAM,YAAY,KAAK,eAAe,IAAI;AAC1C,QAAI;AAAW,aAAO;AAGtB,WAAO,KAAK,YAAY,IAAI;AAC5B,WAAO,KAAK,gBAAgB,IAAI;AAChC,WAAO,KAAK,cAAc,MAAM,aAAa;AAC7C,WAAO,KAAK,gBAAgB,IAAI;AAChC,WAAO,KAAK,kBAAkB,IAAI;AAGlC,WAAO,KAAK,oBAAoB,IAAI;AAGpC,QAAI,KAAK,KAAK,MAAM,IAAI;AAGtB,aAAO;AAAA,IACT;AAEA,WAAO,QAAQ,IAAI;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,MAAM,MAAM,aAAa,IAAI,oBAAoB,OAAO,qBAAqB,gBAAgB,OAAO;AAEzG,SAAK,eAAe;AAEpB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,cAAc;AAElB,UAAM,cAAc,MAAM,IAAI,CAAC,MAAM,UAAU;AAE7C,UAAI,qBAAqB,UAAU,YAAY;AAC7C,cAAM,UAAU,KAAK,WAAW,IAAI,KAAK;AACzC,eAAO,yBAAyB,OAAO;AAAA,MACzC;AAGA,YAAM,iBAAiB;AACvB,UAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,sBAAc,CAAC;AAEf,eAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,MACnE;AAGA,UAAI,aAAa;AACf,cAAM,UAAU,KAAK,WAAW,IAAI;AACpC,cAAM,WAAW,KAAK,oBAAoB,SAAS,IAAI;AACvD,eAAO,QAAQ,YAAY,QAAQ;AAAA,MACrC;AAGA,aAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,IACnE,CAAC;AAGD,UAAM,OAAO,YAAY,KAAK,EAAE;AAGhC,WAAO,KAAK,gBAAgB,MAAM,mBAAmB;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,gBAAgB,MAAM,qBAAqB;AAEhD,QAAI,OAAO,aAAa,eAAe,CAAC,UAAU;AAEhD,aAAO,KAAK,sBAAsB,MAAM,mBAAmB;AAAA,IAC7D;AAGA,UAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,cAAU,YAAY;AAEtB,QAAI,cAAc;AAClB,QAAI,WAAW;AACf,QAAI,mBAAmB;AACvB,QAAI,cAAc;AAGlB,UAAM,WAAW,MAAM,KAAK,UAAU,QAAQ;AAE9C,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,QAAQ,SAAS,CAAC;AAGxB,UAAI,CAAC,MAAM;AAAY;AAGvB,YAAM,YAAY,MAAM,cAAc,aAAa;AACnD,UAAI,WAAW;AACb,cAAM,YAAY,UAAU;AAC5B,YAAI,UAAU,WAAW,KAAK,GAAG;AAC/B,cAAI,CAAC,aAAa;AAEhB,0BAAc;AAGd,+BAAmB,SAAS,cAAc,KAAK;AAC/C,kBAAM,cAAc,SAAS,cAAc,MAAM;AACjD,6BAAiB,YAAY,WAAW;AACxC,6BAAiB,YAAY;AAG7B,kBAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,gBAAI,MAAM;AACR,0BAAY,YAAY,YAAY,IAAI;AAAA,YAC1C;AAGA,sBAAU,aAAa,kBAAkB,MAAM,WAAW;AAG1D,6BAAiB,eAAe;AAChC,6BAAiB,YAAY;AAC7B,6BAAiB,eAAe;AAChC;AAAA,UACF,OAAO;AAGL,kBAAM,cAAc,uBAAuB,KAAK;AAChD,gBAAI,oBAAoB,eAAe,iBAAiB,cAAc;AACpE,kBAAI;AACF,sBAAM,SAAS;AAAA,kBACb,iBAAiB;AAAA,kBACjB,iBAAiB,aAAa;AAAA,gBAChC;AAGA,oBAAI,UAAU,OAAO,OAAO,SAAS,YAAY;AAC/C,0BAAQ,KAAK,kOAAkO;AAAA,gBAEjP,OAAO;AAGL,sBAAI,UAAU,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AACzD,qCAAiB,aAAa,YAAY;AAAA,kBAC5C;AAAA,gBAEF;AAAA,cACF,SAAS,OAAO;AACd,wBAAQ,KAAK,6BAA6B,KAAK;AAAA,cAEjD;AAAA,YACF;AAEA,0BAAc;AACd,+BAAmB;AACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,eAAe,oBAAoB,MAAM,YAAY,SAAS,CAAC,MAAM,cAAc,aAAa,GAAG;AACrG,cAAM,cAAc,iBAAiB,gBAAgB,iBAAiB,cAAc,MAAM;AAE1F,YAAI,iBAAiB,aAAa,SAAS,GAAG;AAC5C,2BAAiB,gBAAgB;AAAA,QACnC;AAEA,cAAM,WAAW,MAAM,YAAY,QAAQ,WAAW,GAAG;AACzD,yBAAiB,gBAAgB;AAGjC,YAAI,YAAY,YAAY,SAAS,GAAG;AACtC,sBAAY,eAAe;AAAA,QAC7B;AACA,oBAAY,eAAe;AAC3B,cAAM,OAAO;AACb;AAAA,MACF;AAGA,UAAI,WAAW;AACf,UAAI,MAAM,YAAY,OAAO;AAE3B,mBAAW,MAAM,cAAc,IAAI;AAAA,MACrC;AAEA,UAAI,UAAU;AACZ,cAAM,WAAW,SAAS,UAAU,SAAS,aAAa;AAC1D,cAAM,YAAY,SAAS,UAAU,SAAS,cAAc;AAE5D,YAAI,CAAC,YAAY,CAAC,WAAW;AAC3B,wBAAc;AACd,qBAAW;AACX;AAAA,QACF;AAEA,cAAM,UAAU,WAAW,OAAO;AAGlC,YAAI,CAAC,eAAe,aAAa,SAAS;AACxC,wBAAc,SAAS,cAAc,OAAO;AAC5C,oBAAU,aAAa,aAAa,KAAK;AACzC,qBAAW;AAAA,QACb;AAGA,cAAM,mBAAmB,CAAC;AAC1B,mBAAW,QAAQ,MAAM,YAAY;AACnC,cAAI,KAAK,aAAa,KAAK,KAAK,YAAY,MAAM,WAAW,GAAG;AAE9D,6BAAiB,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,UAC5C,WAAW,SAAS,UAAU;AAC5B;AAAA,UACF;AAAA,QACF;AAGA,yBAAiB,QAAQ,UAAQ;AAC/B,mBAAS,aAAa,MAAM,SAAS,UAAU;AAAA,QACjD,CAAC;AAGD,oBAAY,YAAY,QAAQ;AAGhC,cAAM,OAAO;AAAA,MACf,OAAO;AAEL,sBAAc;AACd,mBAAW;AAAA,MACb;AAAA,IACF;AAEA,WAAO,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,sBAAsB,MAAM,qBAAqB;AACtD,QAAI,YAAY;AAGhB,gBAAY,UAAU,QAAQ,wEAAwE,CAAC,UAAU;AAC/G,YAAM,OAAO,MAAM,MAAM,4DAA4D,KAAK,CAAC;AAC3F,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,gBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,gBAAM,gBAAgB,IAAI,MAAM,mCAAmC;AAEnE,cAAI,eAAe,eAAe;AAChC,kBAAM,cAAc,YAAY,CAAC;AACjC,kBAAM,WAAW,cAAc,CAAC;AAEhC,mBAAO,SAAS,QAAQ,4BAA4B,2BAA2B,WAAW,EAAE;AAAA,UAC9F;AACA,iBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,QAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,MACnC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,gBAAY,UAAU,QAAQ,yEAAyE,CAAC,UAAU;AAChH,YAAM,OAAO,MAAM,MAAM,6DAA6D,KAAK,CAAC;AAC5F,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,gBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,gBAAM,gBAAgB,IAAI,MAAM,oCAAoC;AAEpE,cAAI,eAAe,eAAe;AAChC,kBAAM,cAAc,YAAY,CAAC;AACjC,kBAAM,WAAW,cAAc,CAAC;AAEhC,mBAAO,SAAS,QAAQ,6BAA6B,4BAA4B,WAAW,EAAE;AAAA,UAChG;AACA,iBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,QAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,MACnC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,UAAM,iBAAiB;AACvB,gBAAY,UAAU,QAAQ,gBAAgB,CAAC,OAAO,WAAW,SAAS,eAAe;AAEvF,YAAM,QAAQ,QAAQ,MAAM,qBAAqB,KAAK,CAAC;AACvD,YAAM,cAAc,MAAM,IAAI,UAAQ;AAEpC,cAAM,OAAO,KAAK,QAAQ,sBAAsB,IAAI,EACjD,QAAQ,WAAW,GAAG;AACzB,eAAO;AAAA,MACT,CAAC,EAAE,KAAK,IAAI;AAGZ,YAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,YAAM,YAAY,OAAO,oBAAoB,IAAI,MAAM;AAGvD,UAAI,qBAAqB;AAEzB,YAAM,cAAc,uBAAuB,KAAK;AAChD,UAAI,aAAa;AACf,YAAI;AAIF,gBAAM,cAAc,YACjB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,UAAU,GAAG;AAExB,gBAAMA,UAAS,YAAY,aAAa,IAAI;AAI5C,cAAIA,WAAU,OAAOA,QAAO,SAAS,YAAY;AAC/C,oBAAQ,KAAK,4HAA4H;AAAA,UAE3I,OAAO;AAEL,gBAAIA,WAAU,OAAOA,YAAW,YAAYA,QAAO,KAAK,GAAG;AACzD,mCAAqBA;AAAA,YACvB;AAAA,UAEF;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,KAAK,6BAA6B,KAAK;AAAA,QAEjD;AAAA,MACF;AAGA,UAAI,SAAS,iCAAiC,SAAS;AAEvD,gBAAU,gCAAgC,SAAS,IAAI,kBAAkB;AACzE,gBAAU,iCAAiC,UAAU;AAErD,aAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,eAAe,MAAM,gBAAgB;AAE1C,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,aAAa;AACjB,QAAI,YAAY;AAChB,QAAI,YAAY;AAEhB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,aAAa,MAAM,CAAC,EAAE;AAC5B,UAAI,aAAa,cAAc,gBAAgB;AAC7C,oBAAY;AACZ,oBAAY;AACZ;AAAA,MACF;AACA,oBAAc,aAAa;AAAA,IAC7B;AAEA,UAAM,cAAc,MAAM,SAAS;AACnC,UAAM,UAAU,YAAY,YAAY;AAGxC,UAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,cAAc,CAAC;AAAA,QACvB,QAAQ;AAAA,QACR,SAAS,cAAc,CAAC,MAAM;AAAA,QAC9B,SAAS,cAAc,CAAC;AAAA,QACxB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,MAChF;AAAA,IACF;AAGA,UAAM,cAAc,YAAY,MAAM,KAAK,cAAc,MAAM;AAC/D,QAAI,aAAa;AACf,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,YAAY,CAAC;AAAA,QACrB,QAAQ,YAAY,CAAC;AAAA,QACrB,SAAS,YAAY,CAAC;AAAA,QACtB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,YAAY,CAAC,EAAE,SAAS,YAAY,CAAC,EAAE,SAAS;AAAA;AAAA,MAC5E;AAAA,IACF;AAGA,UAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,cAAc,CAAC;AAAA,QACvB,QAAQ,SAAS,cAAc,CAAC,CAAC;AAAA,QACjC,SAAS,cAAc,CAAC;AAAA,QACxB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,MAChF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,SAAS;AAChC,YAAQ,QAAQ,UAAU;AAAA,MACxB,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,MAAM;AAAA,MAC3C,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,SAAS,CAAC;AAAA,MAC/C,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM;AAAA,MAC1B;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,cAAc,MAAM;AACzB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,kBAAkB,oBAAI,IAAI;AAChC,QAAI,SAAS;AAEb,UAAM,SAAS,MAAM,IAAI,UAAQ;AAC/B,YAAM,QAAQ,KAAK,MAAM,KAAK,cAAc,QAAQ;AAEpD,UAAI,OAAO;AACT,cAAM,SAAS,MAAM,CAAC;AACtB,cAAM,cAAc,OAAO;AAC3B,cAAM,UAAU,MAAM,CAAC;AAGvB,YAAI,CAAC,QAAQ;AACX,0BAAgB,MAAM;AAAA,QACxB;AAGA,cAAM,iBAAiB,gBAAgB,IAAI,WAAW,KAAK,KAAK;AAChE,wBAAgB,IAAI,aAAa,aAAa;AAG9C,mBAAW,CAAC,KAAK,KAAK,iBAAiB;AACrC,cAAI,QAAQ,aAAa;AACvB,4BAAgB,OAAO,KAAK;AAAA,UAC9B;AAAA,QACF;AAEA,iBAAS;AACT,eAAO,GAAG,MAAM,GAAG,aAAa,KAAK,OAAO;AAAA,MAC9C,OAAO;AAEL,YAAI,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,MAAM,KAAK,GAAG;AAE5C,mBAAS;AACT,0BAAgB,MAAM;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,OAAO,KAAK,IAAI;AAAA,EACzB;AACF;AAAA;AA18BE,cAFW,gBAEJ,aAAY;AAAA;AAGnB,cALW,gBAKJ,mBAAkB;AAAA;AAGzB,cARW,gBAQJ,gBAAe;AAAA;AAAA;AAAA;AAsyBtB,cA9yBW,gBA8yBJ,iBAAgB;AAAA,EACrB,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AACZ;;;AClzBK,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAY,QAAQ;AAClB,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,OAAO;AACnB,UAAM,QAAQ,UAAU,SAAS,YAAY,EAAE,SAAS,KAAK;AAC7D,UAAM,SAAS,QAAQ,MAAM,UAAU,MAAM;AAE7C,QAAI,CAAC;AAAQ,aAAO;AAEpB,QAAI,WAAW;AAEf,YAAQ,MAAM,IAAI,YAAY,GAAG;AAAA,MAC/B,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,MAAM;AAAU,qBAAW;AAC/B;AAAA,MACF,KAAK;AACH,YAAI,MAAM;AAAU,qBAAW;AAC/B;AAAA,IACJ;AAEA,QAAI,UAAU;AACZ,YAAM,eAAe;AACrB,WAAK,OAAO,cAAc,UAAU,KAAK;AACzC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,EAEV;AACF;;;ACnDO,IAAM,QAAQ;AAAA,EACnB,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,MAAM;AAAA;AAAA,IACN,aAAa;AAAA;AAAA,IACb,eAAe;AAAA;AAAA,IACf,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,QAAQ;AAAA;AAAA,IACR,IAAI;AAAA;AAAA,IACJ,KAAK;AAAA;AAAA,IACL,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA;AAAA,IACR,YAAY;AAAA;AAAA,IACZ,IAAI;AAAA;AAAA,IACJ,cAAc;AAAA;AAAA,IACd,QAAQ;AAAA;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,SAAS;AAAA;AAAA,IACT,QAAQ;AAAA;AAAA,IACR,SAAS;AAAA;AAAA,IACT,SAAS;AAAA;AAAA;AAAA,IAET,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,eAAe;AAAA;AAAA,EACjB;AACF;AAKO,IAAM,OAAO;AAAA,EAClB,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,MAAM;AAAA;AAAA,IACN,aAAa;AAAA;AAAA,IACb,eAAe;AAAA;AAAA,IACf,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,QAAQ;AAAA;AAAA,IACR,IAAI;AAAA;AAAA,IACJ,KAAK;AAAA;AAAA,IACL,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA;AAAA,IACR,YAAY;AAAA;AAAA,IACZ,IAAI;AAAA;AAAA,IACJ,cAAc;AAAA;AAAA,IACd,QAAQ;AAAA;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,SAAS;AAAA;AAAA,IACT,QAAQ;AAAA;AAAA,IACR,SAAS;AAAA;AAAA,IACT,SAAS;AAAA;AAAA;AAAA,IAET,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,eAAe;AAAA;AAAA,EACjB;AACF;AAMO,IAAM,OAAO;AAAA,EAClB,MAAM;AAAA;AAAA,EAEN,QAAQ,MAAM;AAAA;AAChB;AAKO,IAAM,SAAS;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,OAAO;AAAA,EACP,MAAM;AACR;AAOO,SAAS,SAAS,OAAO;AAC9B,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AAEzC,WAAO,EAAE,GAAG,UAAU,MAAM,MAAM;AAAA,EACpC;AACA,SAAO;AACT;AAGA,IAAI,MAAM;AAOH,SAAS,iBAAiB,WAAW;AAC1C,MAAI,cAAc;AAAQ,WAAO;AAGjC,MAAI,CAAC,OAAO,OAAO,YAAY;AAC7B,UAAM,OAAO,WAAW,8BAA8B;AAAA,EACxD;AAEA,UAAO,2BAAK,WAAU,SAAS;AACjC;AAmBO,SAAS,eAAe,QAAQ;AACrC,QAAM,OAAO,CAAC;AACd,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAEjD,UAAM,UAAU,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC3D,SAAK,KAAK,KAAK,OAAO,KAAK,KAAK,GAAG;AAAA,EACrC;AACA,SAAO,KAAK,KAAK,IAAI;AACvB;AAQO,SAAS,WAAW,WAAW,eAAe,CAAC,GAAG;AACvD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ;AAAA,MACN,GAAG,UAAU;AAAA,MACb,GAAG;AAAA,IACL;AAAA,EACF;AACF;;;ACvKO,SAAS,eAAe,UAAU,CAAC,GAAG;AAC3C,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,aAAa;AAAA;AAAA,IAEb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS,CAAC;AAAA,EACZ,IAAI;AAGJ,QAAM,eAAe,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI;AAAA;AAAA;AAAA;AAAA,UAI9C,OAAO,QAAQ,MAAM,EACpB,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AACpB,UAAM,UAAU,KAAK,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC5D,WAAO,GAAG,OAAO,KAAK,GAAG;AAAA,EAC3B,CAAC,EACA,KAAK,YAAY,CAAC;AAAA;AAAA;AAAA,MAGvB;AAGJ,QAAM,YAAY,SAAS,MAAM,SAAS,eAAe,MAAM,MAAM,IAAI;AAEzE,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAyCD,YAAY;AAAA;AAAA,QAEZ,SAAS,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAyCH,UAAU;AAAA;AAAA,6CAEc,QAAQ;AAAA,iDACJ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCASlB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;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", + "sourcesContent": ["/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n", "/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n // Instance-level auto theme tracking (when individual instances use auto theme)\n static _mq = null; // Shared media query for instance auto themes\n static _mqListener = null; // Shared listener for instance auto themes\n static _autoInstances = new Set(); // Track instances using auto theme\n // Global-level auto theme tracking (when OverType.setTheme('auto') is called)\n static _globalAutoMq = null; // Media query for global auto theme\n static _globalAutoListener = null; // Listener for global auto theme\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n const setTheme = (el) => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n };\n \n document.querySelectorAll('.overtype-container').forEach(setTheme);\n \n document.querySelectorAll('.overtype-wrapper').forEach(w => {\n if (!w.closest('.overtype-container')) setTheme(w);\n w._instance?.updatePreview();\n });\n \n document.querySelectorAll('overtype-editor').forEach(wc => {\n wc.setAttribute?.('theme', isAuto ? 'auto' : themeName);\n if (isAuto) wc.setAttribute?.('data-resolved-theme', themeName);\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n"], + "mappings": ";;;;;;;;;;;;;;;AAQO,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA,EAa1B,OAAO,iBAAiB;AACtB,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,mBAAmB,aAAa;AACrC,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,gBAAgB,WAAW;AAChC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,MAAM;AAC7B,QAAI,KAAK,cAAc;AACrB,aAAO,KAAK,aAAa,IAAI;AAAA,IAC/B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WAAW,MAAM;AACtB,UAAM,MAAM;AAAA,MACV,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,WAAO,KAAK,QAAQ,YAAY,OAAK,IAAI,CAAC,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,oBAAoB,MAAM,cAAc;AAC7C,UAAM,gBAAgB,aAAa,MAAM,QAAQ,EAAE,CAAC;AACpD,UAAM,cAAc,cAAc,QAAQ,MAAM,QAAQ;AACxD,WAAO,KAAK,QAAQ,QAAQ,WAAW;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,MAAM;AACvB,WAAO,KAAK,QAAQ,oBAAoB,CAAC,OAAO,QAAQ,YAAY;AAClE,YAAM,QAAQ,OAAO;AACrB,aAAO,KAAK,KAAK,gCAAgC,MAAM,WAAW,OAAO,MAAM,KAAK;AAAA,IACtF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,oBAAoB,MAAM;AAC/B,QAAI,KAAK,MAAM,wBAAwB,GAAG;AACxC,aAAO,gCAAgC,IAAI;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAC3B,WAAO,KAAK,QAAQ,eAAe,CAAC,OAAO,YAAY;AACrD,aAAO,oEAAoE,OAAO;AAAA,IACpF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAC3B,WAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,aAAO,GAAG,MAAM,uDAAuD,MAAM,WAAW,OAAO;AAAA,IACjG,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,cAAc,MAAM,gBAAgB,OAAO;AAChD,WAAO,KAAK,QAAQ,yCAAyC,CAAC,OAAO,QAAQ,SAAS,YAAY;AAChG,UAAI,eAAe;AAEjB,cAAM,YAAY,QAAQ,YAAY,MAAM;AAC5C,eAAO,GAAG,MAAM,gDAAgD,YAAY,YAAY,EAAE,KAAK,OAAO;AAAA,MACxG,OAAO;AAEL,eAAO,GAAG,MAAM,wDAAwD,OAAO,YAAY,OAAO;AAAA,MACpG;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,MAAM;AAC7B,WAAO,KAAK,QAAQ,gCAAgC,CAAC,OAAO,QAAQ,QAAQ,YAAY;AACtF,aAAO,GAAG,MAAM,wDAAwD,MAAM,WAAW,OAAO;AAAA,IAClG,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,eAAe,MAAM;AAE1B,UAAM,iBAAiB;AACvB,QAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,aAAO,iCAAiC,IAAI;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAAM;AACrB,WAAO,KAAK,QAAQ,kBAAkB,+FAA+F;AACrI,WAAO,KAAK,QAAQ,cAAc,+FAA+F;AACjI,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,YAAY,MAAM;AAGvB,WAAO,KAAK,QAAQ,WAAC,gDAAuC,GAAC,GAAE,qFAAqF;AAIpJ,WAAO,KAAK,QAAQ,WAAC,8CAAyC,GAAC,GAAE,qFAAqF;AAEtJ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,mBAAmB,MAAM;AAE9B,WAAO,KAAK,QAAQ,WAAC,mCAAgC,GAAC,GAAE,yFAAyF;AAEjJ,WAAO,KAAK,QAAQ,WAAC,iCAA8B,GAAC,GAAE,uFAAuF;AAC7I,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,gBAAgB,MAAM;AAS3B,WAAO,KAAK,QAAQ,WAAC,6CAAwC,GAAC,GAAE,2FAA2F;AAAA,EAC7J;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,YAAY,KAAK;AAEtB,UAAM,UAAU,IAAI,KAAK;AACzB,UAAM,QAAQ,QAAQ,YAAY;AAGlC,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,kBAAkB,cAAc,KAAK,cAAY,MAAM,WAAW,QAAQ,CAAC;AAGjF,UAAM,aAAa,QAAQ,WAAW,GAAG,KACvB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,GAAG,KACrB,CAAC,QAAQ,SAAS,GAAG,KAAK,CAAC,QAAQ,SAAS,IAAI;AAGnE,QAAI,mBAAmB,YAAY;AACjC,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,WAAW,MAAM;AACtB,WAAO,KAAK,QAAQ,uBAAuB,CAAC,OAAO,MAAM,QAAQ;AAC/D,YAAM,aAAa,UAAU,KAAK,WAAW;AAE7C,YAAM,UAAU,KAAK,YAAY,GAAG;AAEpC,aAAO,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,IAAI,0CAA0C,GAAG;AAAA,IACzJ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,8BAA8B,MAAM;AACzC,UAAM,cAAc,oBAAI,IAAI;AAC5B,QAAI,mBAAmB;AACvB,QAAI,gBAAgB;AAGpB,UAAM,mBAAmB,CAAC;AAG1B,UAAM,YAAY;AAClB,QAAI;AACJ,YAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAIlD,YAAM,aAAa,UAAU,QAAQ,UAAU,CAAC,EAAE,QAAQ,IAAI;AAC9D,YAAM,WAAW,aAAa;AAC9B,YAAM,SAAS,WAAW,UAAU,CAAC,EAAE;AACvC,uBAAiB,KAAK,EAAE,OAAO,UAAU,KAAK,OAAO,CAAC;AAAA,IACxD;AAGA,UAAM,YAAY,WAAC,6CAAwC,GAAC;AAC5D,QAAI;AACJ,UAAM,cAAc,CAAC;AAErB,YAAQ,YAAY,UAAU,KAAK,IAAI,OAAO,MAAM;AAClD,YAAM,YAAY,UAAU;AAC5B,YAAM,UAAU,UAAU,QAAQ,UAAU,CAAC,EAAE;AAG/C,YAAM,oBAAoB,iBAAiB;AAAA,QAAK,YAC9C,aAAa,OAAO,SAAS,WAAW,OAAO;AAAA,MACjD;AAEA,UAAI,CAAC,mBAAmB;AACtB,oBAAY,KAAK;AAAA,UACf,OAAO,UAAU,CAAC;AAAA,UAClB,OAAO,UAAU;AAAA,UACjB,WAAW,UAAU,CAAC;AAAA,UACtB,SAAS,UAAU,CAAC;AAAA,UACpB,YAAY,UAAU,CAAC;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,IACF;AAGA,gBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC5C,gBAAY,QAAQ,cAAY;AAC9B,YAAM,cAAc,SAAS,kBAAkB;AAC/C,kBAAY,IAAI,aAAa;AAAA,QAC3B,MAAM;AAAA,QACN,UAAU,SAAS;AAAA,QACnB,WAAW,SAAS;AAAA,QACpB,SAAS,SAAS;AAAA,QAClB,YAAY,SAAS;AAAA,MACvB,CAAC;AACD,sBAAgB,cAAc,UAAU,GAAG,SAAS,KAAK,IAC1C,cACA,cAAc,UAAU,SAAS,QAAQ,SAAS,MAAM,MAAM;AAAA,IAC/E,CAAC;AAGD,oBAAgB,cAAc,QAAQ,4BAA4B,CAAC,OAAO,UAAU,QAAQ;AAC1F,YAAM,cAAc,SAAS,kBAAkB;AAC/C,kBAAY,IAAI,aAAa;AAAA,QAC3B,MAAM;AAAA,QACN,UAAU;AAAA,QACV;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAED,WAAO,EAAE,eAAe,YAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,+BAA+B,MAAM,aAAa;AAEvD,UAAM,eAAe,MAAM,KAAK,YAAY,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM;AACjE,YAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,YAAM,SAAS,KAAK,QAAQ,CAAC;AAC7B,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,iBAAa,QAAQ,iBAAe;AAClC,YAAM,YAAY,YAAY,IAAI,WAAW;AAC7C,UAAI;AAEJ,UAAI,UAAU,SAAS,QAAQ;AAE7B,sBAAc,qCAAqC,UAAU,SAAS,UAAU,UAAU,OAAO,+BAA+B,UAAU,UAAU;AAAA,MACtJ,WAAW,UAAU,SAAS,QAAQ;AAEpC,YAAI,oBAAoB,UAAU;AAIlC,oBAAY,QAAQ,CAAC,gBAAgB,qBAAqB;AACxD,cAAI,kBAAkB,SAAS,gBAAgB,GAAG;AAChD,gBAAI,eAAe,SAAS,QAAQ;AAClC,oBAAM,WAAW,qCAAqC,eAAe,SAAS,UAAU,eAAe,OAAO,+BAA+B,eAAe,UAAU;AACtK,kCAAoB,kBAAkB,QAAQ,kBAAkB,QAAQ;AAAA,YAC1E;AAAA,UACF;AAAA,QACF,CAAC;AAGD,4BAAoB,KAAK,mBAAmB,iBAAiB;AAC7D,4BAAoB,KAAK,UAAU,iBAAiB;AACpD,4BAAoB,KAAK,YAAY,iBAAiB;AAItD,cAAM,aAAa,UAAU,KAAK,WAAW;AAC7C,cAAM,UAAU,KAAK,YAAY,UAAU,GAAG;AAC9C,sBAAc,YAAY,OAAO,yBAAyB,UAAU,yCAAyC,iBAAiB,0CAA0C,UAAU,GAAG;AAAA,MACvL;AAEA,aAAO,KAAK,QAAQ,aAAa,WAAW;AAAA,IAC9C,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,oBAAoB,MAAM;AAE/B,UAAM,EAAE,eAAe,YAAY,IAAI,KAAK,8BAA8B,IAAI;AAG9E,QAAI,OAAO;AACX,WAAO,KAAK,mBAAmB,IAAI;AACnC,WAAO,KAAK,UAAU,IAAI;AAC1B,WAAO,KAAK,YAAY,IAAI;AAG5B,WAAO,KAAK,+BAA+B,MAAM,WAAW;AAE5D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,UAAU,MAAM,gBAAgB,OAAO;AAC5C,QAAI,OAAO,KAAK,WAAW,IAAI;AAG/B,WAAO,KAAK,oBAAoB,MAAM,IAAI;AAG1C,UAAM,iBAAiB,KAAK,oBAAoB,IAAI;AACpD,QAAI;AAAgB,aAAO;AAE3B,UAAM,YAAY,KAAK,eAAe,IAAI;AAC1C,QAAI;AAAW,aAAO;AAGtB,WAAO,KAAK,YAAY,IAAI;AAC5B,WAAO,KAAK,gBAAgB,IAAI;AAChC,WAAO,KAAK,cAAc,MAAM,aAAa;AAC7C,WAAO,KAAK,gBAAgB,IAAI;AAChC,WAAO,KAAK,kBAAkB,IAAI;AAGlC,WAAO,KAAK,oBAAoB,IAAI;AAGpC,QAAI,KAAK,KAAK,MAAM,IAAI;AAGtB,aAAO;AAAA,IACT;AAEA,WAAO,QAAQ,IAAI;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,MAAM,MAAM,aAAa,IAAI,oBAAoB,OAAO,qBAAqB,gBAAgB,OAAO;AAEzG,SAAK,eAAe;AAEpB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,cAAc;AAElB,UAAM,cAAc,MAAM,IAAI,CAAC,MAAM,UAAU;AAE7C,UAAI,qBAAqB,UAAU,YAAY;AAC7C,cAAM,UAAU,KAAK,WAAW,IAAI,KAAK;AACzC,eAAO,yBAAyB,OAAO;AAAA,MACzC;AAGA,YAAM,iBAAiB;AACvB,UAAI,eAAe,KAAK,IAAI,GAAG;AAC7B,sBAAc,CAAC;AAEf,eAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,MACnE;AAGA,UAAI,aAAa;AACf,cAAM,UAAU,KAAK,WAAW,IAAI;AACpC,cAAM,WAAW,KAAK,oBAAoB,SAAS,IAAI;AACvD,eAAO,QAAQ,YAAY,QAAQ;AAAA,MACrC;AAGA,aAAO,KAAK,kBAAkB,KAAK,UAAU,MAAM,aAAa,CAAC;AAAA,IACnE,CAAC;AAGD,UAAM,OAAO,YAAY,KAAK,EAAE;AAGhC,WAAO,KAAK,gBAAgB,MAAM,mBAAmB;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,gBAAgB,MAAM,qBAAqB;AAEhD,QAAI,OAAO,aAAa,eAAe,CAAC,UAAU;AAEhD,aAAO,KAAK,sBAAsB,MAAM,mBAAmB;AAAA,IAC7D;AAGA,UAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,cAAU,YAAY;AAEtB,QAAI,cAAc;AAClB,QAAI,WAAW;AACf,QAAI,mBAAmB;AACvB,QAAI,cAAc;AAGlB,UAAM,WAAW,MAAM,KAAK,UAAU,QAAQ;AAE9C,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,QAAQ,SAAS,CAAC;AAGxB,UAAI,CAAC,MAAM;AAAY;AAGvB,YAAM,YAAY,MAAM,cAAc,aAAa;AACnD,UAAI,WAAW;AACb,cAAM,YAAY,UAAU;AAC5B,YAAI,UAAU,WAAW,KAAK,GAAG;AAC/B,cAAI,CAAC,aAAa;AAEhB,0BAAc;AAGd,+BAAmB,SAAS,cAAc,KAAK;AAC/C,kBAAM,cAAc,SAAS,cAAc,MAAM;AACjD,6BAAiB,YAAY,WAAW;AACxC,6BAAiB,YAAY;AAG7B,kBAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,gBAAI,MAAM;AACR,0BAAY,YAAY,YAAY,IAAI;AAAA,YAC1C;AAGA,sBAAU,aAAa,kBAAkB,MAAM,WAAW;AAG1D,6BAAiB,eAAe;AAChC,6BAAiB,YAAY;AAC7B,6BAAiB,eAAe;AAChC;AAAA,UACF,OAAO;AAGL,kBAAM,cAAc,uBAAuB,KAAK;AAChD,gBAAI,oBAAoB,eAAe,iBAAiB,cAAc;AACpE,kBAAI;AACF,sBAAM,SAAS;AAAA,kBACb,iBAAiB;AAAA,kBACjB,iBAAiB,aAAa;AAAA,gBAChC;AAGA,oBAAI,UAAU,OAAO,OAAO,SAAS,YAAY;AAC/C,0BAAQ,KAAK,kOAAkO;AAAA,gBAEjP,OAAO;AAGL,sBAAI,UAAU,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AACzD,qCAAiB,aAAa,YAAY;AAAA,kBAC5C;AAAA,gBAEF;AAAA,cACF,SAAS,OAAO;AACd,wBAAQ,KAAK,6BAA6B,KAAK;AAAA,cAEjD;AAAA,YACF;AAEA,0BAAc;AACd,+BAAmB;AACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,eAAe,oBAAoB,MAAM,YAAY,SAAS,CAAC,MAAM,cAAc,aAAa,GAAG;AACrG,cAAM,cAAc,iBAAiB,gBAAgB,iBAAiB,cAAc,MAAM;AAE1F,YAAI,iBAAiB,aAAa,SAAS,GAAG;AAC5C,2BAAiB,gBAAgB;AAAA,QACnC;AAEA,cAAM,WAAW,MAAM,YAAY,QAAQ,WAAW,GAAG;AACzD,yBAAiB,gBAAgB;AAGjC,YAAI,YAAY,YAAY,SAAS,GAAG;AACtC,sBAAY,eAAe;AAAA,QAC7B;AACA,oBAAY,eAAe;AAC3B,cAAM,OAAO;AACb;AAAA,MACF;AAGA,UAAI,WAAW;AACf,UAAI,MAAM,YAAY,OAAO;AAE3B,mBAAW,MAAM,cAAc,IAAI;AAAA,MACrC;AAEA,UAAI,UAAU;AACZ,cAAM,WAAW,SAAS,UAAU,SAAS,aAAa;AAC1D,cAAM,YAAY,SAAS,UAAU,SAAS,cAAc;AAE5D,YAAI,CAAC,YAAY,CAAC,WAAW;AAC3B,wBAAc;AACd,qBAAW;AACX;AAAA,QACF;AAEA,cAAM,UAAU,WAAW,OAAO;AAGlC,YAAI,CAAC,eAAe,aAAa,SAAS;AACxC,wBAAc,SAAS,cAAc,OAAO;AAC5C,oBAAU,aAAa,aAAa,KAAK;AACzC,qBAAW;AAAA,QACb;AAGA,cAAM,mBAAmB,CAAC;AAC1B,mBAAW,QAAQ,MAAM,YAAY;AACnC,cAAI,KAAK,aAAa,KAAK,KAAK,YAAY,MAAM,WAAW,GAAG;AAE9D,6BAAiB,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,UAC5C,WAAW,SAAS,UAAU;AAC5B;AAAA,UACF;AAAA,QACF;AAGA,yBAAiB,QAAQ,UAAQ;AAC/B,mBAAS,aAAa,MAAM,SAAS,UAAU;AAAA,QACjD,CAAC;AAGD,oBAAY,YAAY,QAAQ;AAGhC,cAAM,OAAO;AAAA,MACf,OAAO;AAEL,sBAAc;AACd,mBAAW;AAAA,MACb;AAAA,IACF;AAEA,WAAO,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,sBAAsB,MAAM,qBAAqB;AACtD,QAAI,YAAY;AAGhB,gBAAY,UAAU,QAAQ,wEAAwE,CAAC,UAAU;AAC/G,YAAM,OAAO,MAAM,MAAM,4DAA4D,KAAK,CAAC;AAC3F,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,gBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,gBAAM,gBAAgB,IAAI,MAAM,mCAAmC;AAEnE,cAAI,eAAe,eAAe;AAChC,kBAAM,cAAc,YAAY,CAAC;AACjC,kBAAM,WAAW,cAAc,CAAC;AAEhC,mBAAO,SAAS,QAAQ,4BAA4B,2BAA2B,WAAW,EAAE;AAAA,UAC9F;AACA,iBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,QAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,MACnC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,gBAAY,UAAU,QAAQ,yEAAyE,CAAC,UAAU;AAChH,YAAM,OAAO,MAAM,MAAM,6DAA6D,KAAK,CAAC;AAC5F,UAAI,KAAK,SAAS,GAAG;AACnB,cAAM,QAAQ,KAAK,IAAI,SAAO;AAE5B,gBAAM,cAAc,IAAI,MAAM,uBAAuB;AACrD,gBAAM,gBAAgB,IAAI,MAAM,oCAAoC;AAEpE,cAAI,eAAe,eAAe;AAChC,kBAAM,cAAc,YAAY,CAAC;AACjC,kBAAM,WAAW,cAAc,CAAC;AAEhC,mBAAO,SAAS,QAAQ,6BAA6B,4BAA4B,WAAW,EAAE;AAAA,UAChG;AACA,iBAAO,gBAAgB,cAAc,CAAC,IAAI;AAAA,QAC5C,CAAC,EAAE,OAAO,OAAO;AAEjB,eAAO,SAAS,MAAM,KAAK,EAAE,IAAI;AAAA,MACnC;AACA,aAAO;AAAA,IACT,CAAC;AAGD,UAAM,iBAAiB;AACvB,gBAAY,UAAU,QAAQ,gBAAgB,CAAC,OAAO,WAAW,SAAS,eAAe;AAEvF,YAAM,QAAQ,QAAQ,MAAM,qBAAqB,KAAK,CAAC;AACvD,YAAM,cAAc,MAAM,IAAI,UAAQ;AAEpC,cAAM,OAAO,KAAK,QAAQ,sBAAsB,IAAI,EACjD,QAAQ,WAAW,GAAG;AACzB,eAAO;AAAA,MACT,CAAC,EAAE,KAAK,IAAI;AAGZ,YAAM,OAAO,UAAU,MAAM,CAAC,EAAE,KAAK;AACrC,YAAM,YAAY,OAAO,oBAAoB,IAAI,MAAM;AAGvD,UAAI,qBAAqB;AAEzB,YAAM,cAAc,uBAAuB,KAAK;AAChD,UAAI,aAAa;AACf,YAAI;AAIF,gBAAM,cAAc,YACjB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,UAAU,GAAG;AAExB,gBAAMA,UAAS,YAAY,aAAa,IAAI;AAI5C,cAAIA,WAAU,OAAOA,QAAO,SAAS,YAAY;AAC/C,oBAAQ,KAAK,4HAA4H;AAAA,UAE3I,OAAO;AAEL,gBAAIA,WAAU,OAAOA,YAAW,YAAYA,QAAO,KAAK,GAAG;AACzD,mCAAqBA;AAAA,YACvB;AAAA,UAEF;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,KAAK,6BAA6B,KAAK;AAAA,QAEjD;AAAA,MACF;AAGA,UAAI,SAAS,iCAAiC,SAAS;AAEvD,gBAAU,gCAAgC,SAAS,IAAI,kBAAkB;AACzE,gBAAU,iCAAiC,UAAU;AAErD,aAAO;AAAA,IACT,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,eAAe,MAAM,gBAAgB;AAE1C,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,aAAa;AACjB,QAAI,YAAY;AAChB,QAAI,YAAY;AAEhB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,aAAa,MAAM,CAAC,EAAE;AAC5B,UAAI,aAAa,cAAc,gBAAgB;AAC7C,oBAAY;AACZ,oBAAY;AACZ;AAAA,MACF;AACA,oBAAc,aAAa;AAAA,IAC7B;AAEA,UAAM,cAAc,MAAM,SAAS;AACnC,UAAM,UAAU,YAAY,YAAY;AAGxC,UAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,cAAc,CAAC;AAAA,QACvB,QAAQ;AAAA,QACR,SAAS,cAAc,CAAC,MAAM;AAAA,QAC9B,SAAS,cAAc,CAAC;AAAA,QACxB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,MAChF;AAAA,IACF;AAGA,UAAM,cAAc,YAAY,MAAM,KAAK,cAAc,MAAM;AAC/D,QAAI,aAAa;AACf,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,YAAY,CAAC;AAAA,QACrB,QAAQ,YAAY,CAAC;AAAA,QACrB,SAAS,YAAY,CAAC;AAAA,QACtB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,YAAY,CAAC,EAAE,SAAS,YAAY,CAAC,EAAE,SAAS;AAAA;AAAA,MAC5E;AAAA,IACF;AAGA,UAAM,gBAAgB,YAAY,MAAM,KAAK,cAAc,QAAQ;AACnE,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,QAAQ,cAAc,CAAC;AAAA,QACvB,QAAQ,SAAS,cAAc,CAAC,CAAC;AAAA,QACjC,SAAS,cAAc,CAAC;AAAA,QACxB;AAAA,QACA;AAAA,QACA,cAAc,YAAY,cAAc,CAAC,EAAE,SAAS,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA,MAChF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,kBAAkB,SAAS;AAChC,YAAQ,QAAQ,UAAU;AAAA,MACxB,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,MAAM;AAAA,MAC3C,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM,GAAG,QAAQ,SAAS,CAAC;AAAA,MAC/C,KAAK;AACH,eAAO,GAAG,QAAQ,MAAM;AAAA,MAC1B;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,cAAc,MAAM;AACzB,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,kBAAkB,oBAAI,IAAI;AAChC,QAAI,SAAS;AAEb,UAAM,SAAS,MAAM,IAAI,UAAQ;AAC/B,YAAM,QAAQ,KAAK,MAAM,KAAK,cAAc,QAAQ;AAEpD,UAAI,OAAO;AACT,cAAM,SAAS,MAAM,CAAC;AACtB,cAAM,cAAc,OAAO;AAC3B,cAAM,UAAU,MAAM,CAAC;AAGvB,YAAI,CAAC,QAAQ;AACX,0BAAgB,MAAM;AAAA,QACxB;AAGA,cAAM,iBAAiB,gBAAgB,IAAI,WAAW,KAAK,KAAK;AAChE,wBAAgB,IAAI,aAAa,aAAa;AAG9C,mBAAW,CAAC,KAAK,KAAK,iBAAiB;AACrC,cAAI,QAAQ,aAAa;AACvB,4BAAgB,OAAO,KAAK;AAAA,UAC9B;AAAA,QACF;AAEA,iBAAS;AACT,eAAO,GAAG,MAAM,GAAG,aAAa,KAAK,OAAO;AAAA,MAC9C,OAAO;AAEL,YAAI,KAAK,KAAK,MAAM,MAAM,CAAC,KAAK,MAAM,KAAK,GAAG;AAE5C,mBAAS;AACT,0BAAgB,MAAM;AAAA,QACxB;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,OAAO,KAAK,IAAI;AAAA,EACzB;AACF;AAAA;AA18BE,cAFW,gBAEJ,aAAY;AAAA;AAGnB,cALW,gBAKJ,mBAAkB;AAAA;AAGzB,cARW,gBAQJ,gBAAe;AAAA;AAAA;AAAA;AAsyBtB,cA9yBW,gBA8yBJ,iBAAgB;AAAA,EACrB,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AACZ;;;AClzBK,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAY,QAAQ;AAClB,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,OAAO;AACnB,UAAM,QAAQ,UAAU,SAAS,YAAY,EAAE,SAAS,KAAK;AAC7D,UAAM,SAAS,QAAQ,MAAM,UAAU,MAAM;AAE7C,QAAI,CAAC;AAAQ,aAAO;AAEpB,QAAI,WAAW;AAEf,YAAQ,MAAM,IAAI,YAAY,GAAG;AAAA,MAC/B,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,CAAC,MAAM;AAAU,qBAAW;AAChC;AAAA,MACF,KAAK;AACH,YAAI,MAAM;AAAU,qBAAW;AAC/B;AAAA,MACF,KAAK;AACH,YAAI,MAAM;AAAU,qBAAW;AAC/B;AAAA,IACJ;AAEA,QAAI,UAAU;AACZ,YAAM,eAAe;AACrB,WAAK,OAAO,cAAc,UAAU,KAAK;AACzC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AAAA,EAEV;AACF;;;ACnDO,IAAM,QAAQ;AAAA,EACnB,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,MAAM;AAAA;AAAA,IACN,aAAa;AAAA;AAAA,IACb,eAAe;AAAA;AAAA,IACf,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,QAAQ;AAAA;AAAA,IACR,IAAI;AAAA;AAAA,IACJ,KAAK;AAAA;AAAA,IACL,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA;AAAA,IACR,YAAY;AAAA;AAAA,IACZ,IAAI;AAAA;AAAA,IACJ,cAAc;AAAA;AAAA,IACd,QAAQ;AAAA;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,SAAS;AAAA;AAAA,IACT,QAAQ;AAAA;AAAA,IACR,SAAS;AAAA;AAAA,IACT,SAAS;AAAA;AAAA;AAAA,IAET,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,eAAe;AAAA;AAAA,EACjB;AACF;AAKO,IAAM,OAAO;AAAA,EAClB,MAAM;AAAA,EACN,QAAQ;AAAA,IACN,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,MAAM;AAAA;AAAA,IACN,aAAa;AAAA;AAAA,IACb,eAAe;AAAA;AAAA,IACf,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,IAAI;AAAA;AAAA,IACJ,QAAQ;AAAA;AAAA,IACR,IAAI;AAAA;AAAA,IACJ,KAAK;AAAA;AAAA,IACL,MAAM;AAAA;AAAA,IACN,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA;AAAA,IACR,YAAY;AAAA;AAAA,IACZ,IAAI;AAAA;AAAA,IACJ,cAAc;AAAA;AAAA,IACd,QAAQ;AAAA;AAAA,IACR,QAAQ;AAAA;AAAA,IACR,WAAW;AAAA;AAAA,IACX,YAAY;AAAA;AAAA,IACZ,SAAS;AAAA;AAAA,IACT,QAAQ;AAAA;AAAA,IACR,SAAS;AAAA;AAAA,IACT,SAAS;AAAA;AAAA;AAAA,IAET,WAAW;AAAA;AAAA,IACX,aAAa;AAAA;AAAA,IACb,cAAc;AAAA;AAAA,IACd,eAAe;AAAA;AAAA,EACjB;AACF;AAMO,IAAM,OAAO;AAAA,EAClB,MAAM;AAAA;AAAA,EAEN,QAAQ,MAAM;AAAA;AAChB;AAKO,IAAM,SAAS;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,OAAO;AAAA,EACP,MAAM;AACR;AAOO,SAAS,SAAS,OAAO;AAC9B,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AAEzC,WAAO,EAAE,GAAG,UAAU,MAAM,MAAM;AAAA,EACpC;AACA,SAAO;AACT;AAGA,IAAI,MAAM;AAOH,SAAS,iBAAiB,WAAW;AAC1C,MAAI,cAAc;AAAQ,WAAO;AAGjC,MAAI,CAAC,OAAO,OAAO,YAAY;AAC7B,UAAM,OAAO,WAAW,8BAA8B;AAAA,EACxD;AAEA,UAAO,2BAAK,WAAU,SAAS;AACjC;AAmBO,SAAS,eAAe,QAAQ;AACrC,QAAM,OAAO,CAAC;AACd,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAEjD,UAAM,UAAU,IAAI,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC3D,SAAK,KAAK,KAAK,OAAO,KAAK,KAAK,GAAG;AAAA,EACrC;AACA,SAAO,KAAK,KAAK,IAAI;AACvB;AAQO,SAAS,WAAW,WAAW,eAAe,CAAC,GAAG;AACvD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ;AAAA,MACN,GAAG,UAAU;AAAA,MACb,GAAG;AAAA,IACL;AAAA,EACF;AACF;;;ACvKO,SAAS,eAAe,UAAU,CAAC,GAAG;AAC3C,QAAM;AAAA,IACJ,WAAW;AAAA,IACX,aAAa;AAAA;AAAA,IAEb,aAAa;AAAA,IACb,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS,CAAC;AAAA,EACZ,IAAI;AAGJ,QAAM,eAAe,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI;AAAA;AAAA;AAAA;AAAA,UAI9C,OAAO,QAAQ,MAAM,EACpB,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AACpB,UAAM,UAAU,KAAK,QAAQ,YAAY,KAAK,EAAE,YAAY;AAC5D,WAAO,GAAG,OAAO,KAAK,GAAG;AAAA,EAC3B,CAAC,EACA,KAAK,YAAY,CAAC;AAAA;AAAA;AAAA,MAGvB;AAGJ,QAAM,YAAY,SAAS,MAAM,SAAS,eAAe,MAAM,MAAM,IAAI;AAEzE,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAyCD,YAAY;AAAA;AAAA,QAEZ,SAAS,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAyCH,UAAU;AAAA;AAAA,6CAEc,QAAQ;AAAA,iDACJ,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yCASlB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgEzB,YAAY;AAAA;AAElB;;;;;;;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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons"] } diff --git a/dist/overtype.js b/dist/overtype.js index 0dc3228..c396c37 100644 --- a/dist/overtype.js +++ b/dist/overtype.js @@ -3401,7 +3401,7 @@ ${blockSuffix}` : suffix; return false; } var _OverType = class _OverType { - // Global auto theme listener + // Listener for global auto theme /** * Constructor - Always returns an array of instances * @param {string|Element|NodeList|Array} target - Target element(s) @@ -4445,7 +4445,7 @@ ${blockSuffix}` : suffix; }); document.querySelectorAll("overtype-editor").forEach((wc) => { var _a, _b, _c; - (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, isAuto ? "theme" : "theme", isAuto ? "auto" : themeName); + (_a = wc.setAttribute) == null ? void 0 : _a.call(wc, "theme", isAuto ? "auto" : themeName); if (isAuto) (_b = wc.setAttribute) == null ? void 0 : _b.call(wc, "data-resolved-theme", themeName); (_c = wc.refreshTheme) == null ? void 0 : _c.call(wc); @@ -4625,14 +4625,16 @@ ${blockSuffix}` : suffix; __publicField(_OverType, "stylesInjected", false); __publicField(_OverType, "globalListenersInitialized", false); __publicField(_OverType, "instanceCount", 0); + // Instance-level auto theme tracking (when individual instances use auto theme) __publicField(_OverType, "_mq", null); - // Shared media query for auto theme + // Shared media query for instance auto themes __publicField(_OverType, "_mqListener", null); - // Shared listener + // Shared listener for instance auto themes __publicField(_OverType, "_autoInstances", /* @__PURE__ */ new Set()); - // Track auto-themed instances + // Track instances using auto theme + // Global-level auto theme tracking (when OverType.setTheme('auto') is called) __publicField(_OverType, "_globalAutoMq", null); - // Global auto theme media query + // Media query for global auto theme __publicField(_OverType, "_globalAutoListener", null); var OverType = _OverType; OverType.MarkdownParser = MarkdownParser; diff --git a/dist/overtype.js.map b/dist/overtype.js.map index 2c7dc04..e6eadb2 100644 --- a/dist/overtype.js.map +++ b/dist/overtype.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/overtype.js", "../src/parser.js", "../src/shortcuts.js", "../src/themes.js", "../src/styles.js", "../node_modules/markdown-actions/src/core/formats.js", "../node_modules/markdown-actions/src/debug.js", "../node_modules/markdown-actions/src/core/insertion.js", "../node_modules/markdown-actions/src/core/selection.js", "../node_modules/markdown-actions/src/operations/block.js", "../node_modules/markdown-actions/src/operations/list.js", "../node_modules/markdown-actions/src/core/detection.js", "../node_modules/markdown-actions/src/index.js", "../src/toolbar.js", "../src/link-tooltip.js", "../src/icons.js", "../src/toolbar-buttons.js"], - "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n static _mq = null; // Shared media query for auto theme\n static _mqListener = null; // Shared listener\n static _autoInstances = new Set(); // Track auto-themed instances\n static _globalAutoMq = null; // Global auto theme media query\n static _globalAutoListener = null; // Global auto theme listener\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n const setTheme = (el) => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n };\n \n document.querySelectorAll('.overtype-container').forEach(setTheme);\n \n document.querySelectorAll('.overtype-wrapper').forEach(w => {\n if (!w.closest('.overtype-container')) setTheme(w);\n w._instance?.updatePreview();\n });\n \n document.querySelectorAll('overtype-editor').forEach(wc => {\n wc.setAttribute?.(isAuto ? 'theme' : 'theme', isAuto ? 'auto' : themeName);\n if (isAuto) wc.setAttribute?.('data-resolved-theme', themeName);\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], - "mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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", + "sourcesContent": ["/**\n * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment\n * @version 1.0.0\n * @license MIT\n */\n\nimport { MarkdownParser } from './parser.js';\nimport { ShortcutsManager } from './shortcuts.js';\nimport { generateStyles } from './styles.js';\nimport { getTheme, mergeTheme, solar, themeToCSSVars, resolveAutoTheme } from './themes.js';\nimport { Toolbar } from './toolbar.js';\nimport { LinkTooltip } from './link-tooltip.js';\nimport { defaultToolbarButtons } from './toolbar-buttons.js';\n\n/**\n * Build action map from toolbar button configurations\n * @param {Array} buttons - Array of button config objects\n * @returns {Object} Map of actionId -> action function\n */\nfunction buildActionsMap(buttons) {\n const map = {};\n (buttons || []).forEach((btn) => {\n if (!btn || btn.name === 'separator') return;\n const id = btn.actionId || btn.name;\n if (btn.action) {\n map[id] = btn.action;\n }\n });\n return map;\n}\n\n/**\n * Normalize toolbar buttons for comparison\n * @param {Array|null} buttons\n * @returns {Array|null}\n */\nfunction normalizeButtons(buttons) {\n const list = buttons || defaultToolbarButtons;\n if (!Array.isArray(list)) return null;\n return list.map((btn) => ({\n name: btn?.name || null,\n actionId: btn?.actionId || btn?.name || null,\n icon: btn?.icon || null,\n title: btn?.title || null\n }));\n}\n\n/**\n * Determine if toolbar button configuration changed\n * @param {Array|null} prevButtons\n * @param {Array|null} nextButtons\n * @returns {boolean}\n */\nfunction toolbarButtonsChanged(prevButtons, nextButtons) {\n const prev = normalizeButtons(prevButtons);\n const next = normalizeButtons(nextButtons);\n\n if (prev === null || next === null) return prev !== next;\n if (prev.length !== next.length) return true;\n\n for (let i = 0; i < prev.length; i++) {\n const a = prev[i];\n const b = next[i];\n if (a.name !== b.name ||\n a.actionId !== b.actionId ||\n a.icon !== b.icon ||\n a.title !== b.title) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * OverType Editor Class\n */\nclass OverType {\n // Static properties\n static instances = new WeakMap();\n static stylesInjected = false;\n static globalListenersInitialized = false;\n static instanceCount = 0;\n // Instance-level auto theme tracking (when individual instances use auto theme)\n static _mq = null; // Shared media query for instance auto themes\n static _mqListener = null; // Shared listener for instance auto themes\n static _autoInstances = new Set(); // Track instances using auto theme\n // Global-level auto theme tracking (when OverType.setTheme('auto') is called)\n static _globalAutoMq = null; // Media query for global auto theme\n static _globalAutoListener = null; // Listener for global auto theme\n\n /**\n * Constructor - Always returns an array of instances\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n constructor(target, options = {}) {\n // Convert target to array of elements\n let elements;\n \n if (typeof target === 'string') {\n elements = document.querySelectorAll(target);\n if (elements.length === 0) {\n throw new Error(`No elements found for selector: ${target}`);\n }\n elements = Array.from(elements);\n } else if (target instanceof Element) {\n elements = [target];\n } else if (target instanceof NodeList) {\n elements = Array.from(target);\n } else if (Array.isArray(target)) {\n elements = target;\n } else {\n throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');\n }\n\n // Initialize all elements and return array\n const instances = elements.map(element => {\n // Check for existing instance\n if (element.overTypeInstance) {\n // Re-init existing instance\n element.overTypeInstance.reinit(options);\n return element.overTypeInstance;\n }\n\n // Create new instance\n const instance = Object.create(OverType.prototype);\n instance._init(element, options);\n element.overTypeInstance = instance;\n OverType.instances.set(element, instance);\n return instance;\n });\n\n return instances;\n }\n\n /**\n * Internal initialization\n * @private\n */\n _init(element, options = {}) {\n this.element = element;\n \n // Store the original theme option before merging\n this.instanceTheme = options.theme || null;\n \n // Auto theme tracking for instance-level theme\n this.autoThemeMediaQuery = null;\n this.autoThemeListener = null;\n \n this.options = this._mergeOptions(options);\n this.instanceId = ++OverType.instanceCount;\n this.initialized = false;\n\n // Inject styles if needed\n OverType.injectStyles();\n\n // Initialize global listeners\n OverType.initGlobalListeners();\n\n // Check for existing OverType DOM structure\n const container = element.querySelector('.overtype-container');\n const wrapper = element.querySelector('.overtype-wrapper');\n if (container || wrapper) {\n this._recoverFromDOM(container, wrapper);\n } else {\n this._buildFromScratch();\n }\n\n // Set up instance theme if provided (including auto theme listener)\n if (this.instanceTheme) {\n this.setTheme(this.instanceTheme);\n }\n\n // Setup shortcuts manager\n this.shortcuts = new ShortcutsManager(this);\n\n // Build action map from toolbar buttons (works whether or not toolbar UI is shown)\n this._rebuildActionsMap();\n\n // Setup link tooltip\n this.linkTooltip = new LinkTooltip(this);\n\n // Sync scroll positions on initial render\n // This ensures textarea matches preview scroll if page is reloaded while scrolled\n // Double requestAnimationFrame waits for browser to restore scroll position\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n });\n\n // Mark as initialized\n this.initialized = true;\n\n // Call onChange if provided\n if (this.options.onChange) {\n this.options.onChange(this.getValue(), this);\n }\n }\n\n /**\n * Merge user options with defaults\n * @private\n */\n _mergeOptions(options) {\n const defaults = {\n // Typography\n fontSize: '14px',\n lineHeight: 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily: '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding: '16px',\n \n // Mobile styles\n mobile: {\n fontSize: '16px', // Prevent zoom on iOS\n padding: '12px',\n lineHeight: 1.5\n },\n \n // Native textarea properties\n textareaProps: {},\n \n // Behavior\n autofocus: false,\n autoResize: false, // Auto-expand height with content\n minHeight: '100px', // Minimum height for autoResize mode\n maxHeight: null, // Maximum height for autoResize mode (null = unlimited)\n placeholder: 'Start typing...',\n value: '',\n \n // Callbacks\n onChange: null,\n onKeydown: null,\n \n // Features\n showActiveLineRaw: false,\n showStats: false,\n toolbar: false,\n toolbarButtons: null, // Defaults to defaultToolbarButtons if toolbar: true\n statsFormatter: null,\n smartLists: true, // Enable smart list continuation\n codeHighlighter: null // Per-instance code highlighter\n };\n \n // Remove theme and colors from options - these are now global\n const { theme, colors, ...cleanOptions } = options;\n \n return {\n ...defaults,\n ...cleanOptions\n };\n }\n\n /**\n * Recover from existing DOM structure\n * @private\n */\n _recoverFromDOM(container, wrapper) {\n // Handle old structure (wrapper only) or new structure (container + wrapper)\n if (container && container.classList.contains('overtype-container')) {\n this.container = container;\n this.wrapper = container.querySelector('.overtype-wrapper');\n } else if (wrapper) {\n // Old structure - just wrapper, no container\n this.wrapper = wrapper;\n // Wrap it in a container for consistency\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n // Use instance theme if provided, otherwise use global theme\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n wrapper.parentNode.insertBefore(this.container, wrapper);\n this.container.appendChild(wrapper);\n }\n \n if (!this.wrapper) {\n // No valid structure found\n if (container) container.remove();\n if (wrapper) wrapper.remove();\n this._buildFromScratch();\n return;\n }\n \n this.textarea = this.wrapper.querySelector('.overtype-input');\n this.preview = this.wrapper.querySelector('.overtype-preview');\n\n if (!this.textarea || !this.preview) {\n // Partial DOM - clear and rebuild\n this.container.remove();\n this._buildFromScratch();\n return;\n }\n\n // Store reference on wrapper\n this.wrapper._instance = this;\n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n\n // Disable autofill, spellcheck, and extensions\n this._configureTextarea();\n\n // Apply any new options\n this._applyOptions();\n }\n\n /**\n * Build editor from scratch\n * @private\n */\n _buildFromScratch() {\n // Extract any existing content\n const content = this._extractContent();\n\n // Clear element\n this.element.innerHTML = '';\n\n // Create DOM structure\n this._createDOM();\n\n // Set initial content\n if (content || this.options.value) {\n this.setValue(content || this.options.value);\n }\n\n // Apply options\n this._applyOptions();\n }\n\n /**\n * Extract content from element\n * @private\n */\n _extractContent() {\n // Look for existing OverType textarea\n const textarea = this.element.querySelector('.overtype-input');\n if (textarea) return textarea.value;\n\n // Use element's text content as fallback\n return this.element.textContent || '';\n }\n\n /**\n * Create DOM structure\n * @private\n */\n _createDOM() {\n // Create container that will hold toolbar and editor\n this.container = document.createElement('div');\n this.container.className = 'overtype-container';\n \n // Set theme on container - use instance theme if provided\n const themeToUse = this.instanceTheme || OverType.currentTheme || solar;\n const themeName = typeof themeToUse === 'string' ? themeToUse : themeToUse.name;\n if (themeName) {\n this.container.setAttribute('data-theme', themeName);\n }\n \n // If using instance theme, apply CSS variables to container\n if (this.instanceTheme) {\n const themeObj = typeof this.instanceTheme === 'string' ? getTheme(this.instanceTheme) : this.instanceTheme;\n if (themeObj && themeObj.colors) {\n const cssVars = themeToCSSVars(themeObj.colors);\n this.container.style.cssText += cssVars;\n }\n }\n \n // Create wrapper for editor\n this.wrapper = document.createElement('div');\n this.wrapper.className = 'overtype-wrapper';\n \n \n // Apply instance-specific styles via CSS custom properties\n if (this.options.fontSize) {\n this.wrapper.style.setProperty('--instance-font-size', this.options.fontSize);\n }\n if (this.options.lineHeight) {\n this.wrapper.style.setProperty('--instance-line-height', String(this.options.lineHeight));\n }\n if (this.options.padding) {\n this.wrapper.style.setProperty('--instance-padding', this.options.padding);\n }\n \n this.wrapper._instance = this;\n\n // Create textarea\n this.textarea = document.createElement('textarea');\n this.textarea.className = 'overtype-input';\n this.textarea.placeholder = this.options.placeholder;\n this._configureTextarea();\n \n // Apply any native textarea properties\n if (this.options.textareaProps) {\n Object.entries(this.options.textareaProps).forEach(([key, value]) => {\n if (key === 'className' || key === 'class') {\n this.textarea.className += ' ' + value;\n } else if (key === 'style' && typeof value === 'object') {\n Object.assign(this.textarea.style, value);\n } else {\n this.textarea.setAttribute(key, value);\n }\n });\n }\n\n // Create preview div\n this.preview = document.createElement('div');\n this.preview.className = 'overtype-preview';\n this.preview.setAttribute('aria-hidden', 'true');\n\n // Assemble DOM\n this.wrapper.appendChild(this.textarea);\n this.wrapper.appendChild(this.preview);\n \n // No need to prevent link clicks - pointer-events handles this\n \n // Add wrapper to container first\n this.container.appendChild(this.wrapper);\n \n // Add stats bar at the end (bottom) if enabled\n if (this.options.showStats) {\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n }\n \n // Add container to element\n this.element.appendChild(this.container);\n \n // Setup auto-resize if enabled\n if (this.options.autoResize) {\n this._setupAutoResize();\n } else {\n // Ensure auto-resize class is removed if not using auto-resize\n this.container.classList.remove('overtype-auto-resize');\n }\n }\n\n /**\n * Configure textarea attributes\n * @private\n */\n _configureTextarea() {\n this.textarea.setAttribute('autocomplete', 'off');\n this.textarea.setAttribute('autocorrect', 'off');\n this.textarea.setAttribute('autocapitalize', 'off');\n this.textarea.setAttribute('spellcheck', 'false');\n this.textarea.setAttribute('data-gramm', 'false');\n this.textarea.setAttribute('data-gramm_editor', 'false');\n this.textarea.setAttribute('data-enable-grammarly', 'false');\n }\n\n /**\n * Create and setup toolbar\n * @private\n */\n _createToolbar() {\n // Use provided toolbarButtons or default to defaultToolbarButtons\n const toolbarButtons = this.options.toolbarButtons || defaultToolbarButtons;\n\n this.toolbar = new Toolbar(this, { toolbarButtons });\n this.toolbar.create();\n\n // Store listener references for cleanup\n this._toolbarSelectionListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n this._toolbarInputListener = () => {\n if (this.toolbar) {\n this.toolbar.updateButtonStates();\n }\n };\n\n // Add listeners\n this.textarea.addEventListener('selectionchange', this._toolbarSelectionListener);\n this.textarea.addEventListener('input', this._toolbarInputListener);\n }\n\n /**\n * Cleanup toolbar event listeners\n * @private\n */\n _cleanupToolbarListeners() {\n if (this._toolbarSelectionListener) {\n this.textarea.removeEventListener('selectionchange', this._toolbarSelectionListener);\n this._toolbarSelectionListener = null;\n }\n if (this._toolbarInputListener) {\n this.textarea.removeEventListener('input', this._toolbarInputListener);\n this._toolbarInputListener = null;\n }\n }\n\n /**\n * Rebuild the action map from current toolbar button configuration\n * Called during init and reinit to keep shortcuts in sync with toolbar buttons\n * @private\n */\n _rebuildActionsMap() {\n // Always start with default actions (shortcuts always work regardless of toolbar config)\n this.actionsById = buildActionsMap(defaultToolbarButtons);\n\n // Overlay custom toolbar actions (can add/override, but never remove core actions)\n if (this.options.toolbarButtons) {\n Object.assign(this.actionsById, buildActionsMap(this.options.toolbarButtons));\n }\n }\n\n /**\n * Apply options to the editor\n * @private\n */\n _applyOptions() {\n // Apply autofocus\n if (this.options.autofocus) {\n this.textarea.focus();\n }\n\n // Setup or remove auto-resize\n if (this.options.autoResize) {\n if (!this.container.classList.contains('overtype-auto-resize')) {\n this._setupAutoResize();\n }\n } else {\n // Ensure auto-resize class is removed\n this.container.classList.remove('overtype-auto-resize');\n }\n\n // Handle toolbar option changes\n if (this.options.toolbar && !this.toolbar) {\n // Create toolbar if enabled and doesn't exist\n this._createToolbar();\n } else if (!this.options.toolbar && this.toolbar) {\n // Destroy toolbar if disabled and exists\n this._cleanupToolbarListeners();\n this.toolbar.destroy();\n this.toolbar = null;\n }\n\n // Update preview with initial content\n this.updatePreview();\n }\n\n /**\n * Update preview with parsed markdown\n */\n updatePreview() {\n const text = this.textarea.value;\n const cursorPos = this.textarea.selectionStart;\n const activeLine = this._getCurrentLine(text, cursorPos);\n\n // Detect if we're in preview mode\n const isPreviewMode = this.container.dataset.mode === 'preview';\n\n // Parse markdown\n const html = MarkdownParser.parse(text, activeLine, this.options.showActiveLineRaw, this.options.codeHighlighter, isPreviewMode);\n this.preview.innerHTML = html || 'Start typing...';\n \n // Apply code block backgrounds\n this._applyCodeBlockBackgrounds();\n \n // Links always have real hrefs now - no need to update them\n \n // Update stats if enabled\n if (this.options.showStats && this.statsBar) {\n this._updateStats();\n }\n \n // Trigger onChange callback\n if (this.options.onChange && this.initialized) {\n this.options.onChange(text, this);\n }\n }\n\n /**\n * Apply background styling to code blocks\n * @private\n */\n _applyCodeBlockBackgrounds() {\n // Find all code fence elements\n const codeFences = this.preview.querySelectorAll('.code-fence');\n \n // Process pairs of code fences\n for (let i = 0; i < codeFences.length - 1; i += 2) {\n const openFence = codeFences[i];\n const closeFence = codeFences[i + 1];\n \n // Get parent divs\n const openParent = openFence.parentElement;\n const closeParent = closeFence.parentElement;\n \n if (!openParent || !closeParent) continue;\n \n // Make fences display: block\n openFence.style.display = 'block';\n closeFence.style.display = 'block';\n \n // Apply class to parent divs\n openParent.classList.add('code-block-line');\n closeParent.classList.add('code-block-line');\n \n // With the new structure, there's a
     block between fences, not DIVs\n        // We don't need to process anything between the fences anymore\n        // The 
     structure already handles the content correctly\n      }\n    }\n\n    /**\n     * Get current line number from cursor position\n     * @private\n     */\n    _getCurrentLine(text, cursorPos) {\n      const lines = text.substring(0, cursorPos).split('\\n');\n      return lines.length - 1;\n    }\n\n    /**\n     * Handle input events\n     * @private\n     */\n    handleInput(event) {\n      this.updatePreview();\n    }\n\n    /**\n     * Handle keydown events\n     * @private\n     */\n    handleKeydown(event) {\n      // Handle Tab key to prevent focus loss and insert spaces\n      if (event.key === 'Tab') {\n        const start = this.textarea.selectionStart;\n        const end = this.textarea.selectionEnd;\n        const value = this.textarea.value;\n\n        // If Shift+Tab without a selection, allow default behavior (navigate to previous element)\n        if (event.shiftKey && start === end) {\n          return;\n        }\n\n        event.preventDefault();\n\n        // If there's a selection, indent/outdent based on shift key\n        if (start !== end && event.shiftKey) {\n          // Outdent: remove 2 spaces from start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const outdented = lines.map(line => line.replace(/^  /, '')).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, outdented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + outdented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + outdented.length;\n          }\n        } else if (start !== end) {\n          // Indent: add 2 spaces to start of each selected line\n          const before = value.substring(0, start);\n          const selection = value.substring(start, end);\n          const after = value.substring(end);\n          \n          const lines = selection.split('\\n');\n          const indented = lines.map(line => '  ' + line).join('\\n');\n          \n          // Try to use execCommand first to preserve undo history\n          if (document.execCommand) {\n            // Select the text that needs to be replaced\n            this.textarea.setSelectionRange(start, end);\n            document.execCommand('insertText', false, indented);\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = before + indented + after;\n            this.textarea.selectionStart = start;\n            this.textarea.selectionEnd = start + indented.length;\n          }\n        } else {\n          // No selection: just insert 2 spaces\n          // Use execCommand to preserve undo history\n          if (document.execCommand) {\n            document.execCommand('insertText', false, '  ');\n          } else {\n            // Fallback to direct manipulation\n            this.textarea.value = value.substring(0, start) + '  ' + value.substring(end);\n            this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;\n          }\n        }\n        \n        // Trigger input event to update preview\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n        return;\n      }\n      \n      // Handle Enter key for smart list continuation\n      if (event.key === 'Enter' && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {\n        if (this.handleSmartListContinuation()) {\n          event.preventDefault();\n          return;\n        }\n      }\n      \n      // Let shortcuts manager handle other keys\n      const handled = this.shortcuts.handleKeydown(event);\n      \n      // Call user callback if provided\n      if (!handled && this.options.onKeydown) {\n        this.options.onKeydown(event, this);\n      }\n    }\n\n    /**\n     * Handle smart list continuation\n     * @returns {boolean} Whether the event was handled\n     */\n    handleSmartListContinuation() {\n      const textarea = this.textarea;\n      const cursorPos = textarea.selectionStart;\n      const context = MarkdownParser.getListContext(textarea.value, cursorPos);\n      \n      if (!context || !context.inList) return false;\n      \n      // Handle empty list item (exit list)\n      if (context.content.trim() === '' && cursorPos >= context.markerEndPos) {\n        this.deleteListMarker(context);\n        return true;\n      }\n      \n      // Handle text splitting if cursor is in middle of content\n      if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {\n        this.splitListItem(context, cursorPos);\n      } else {\n        // Just add new item after current line\n        this.insertNewListItem(context);\n      }\n      \n      // Handle numbered list renumbering\n      if (context.listType === 'numbered') {\n        this.scheduleNumberedListUpdate();\n      }\n      \n      return true;\n    }\n    \n    /**\n     * Delete list marker and exit list\n     * @private\n     */\n    deleteListMarker(context) {\n      // Select from line start to marker end\n      this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);\n      document.execCommand('delete');\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Insert new list item\n     * @private\n     */\n    insertNewListItem(context) {\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Split list item at cursor position\n     * @private\n     */\n    splitListItem(context, cursorPos) {\n      // Get text after cursor\n      const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);\n      \n      // Delete text after cursor\n      this.textarea.setSelectionRange(cursorPos, context.lineEnd);\n      document.execCommand('delete');\n      \n      // Insert new list item with remaining text\n      const newItem = MarkdownParser.createNewListItem(context);\n      document.execCommand('insertText', false, '\\n' + newItem + textAfterCursor);\n      \n      // Position cursor after new list marker\n      const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;\n      this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n      \n      // Trigger input event\n      this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n    }\n    \n    /**\n     * Schedule numbered list renumbering\n     * @private\n     */\n    scheduleNumberedListUpdate() {\n      // Clear any pending update\n      if (this.numberUpdateTimeout) {\n        clearTimeout(this.numberUpdateTimeout);\n      }\n      \n      // Schedule update after current input cycle\n      this.numberUpdateTimeout = setTimeout(() => {\n        this.updateNumberedLists();\n      }, 10);\n    }\n    \n    /**\n     * Update/renumber all numbered lists\n     * @private\n     */\n    updateNumberedLists() {\n      const value = this.textarea.value;\n      const cursorPos = this.textarea.selectionStart;\n      \n      const newValue = MarkdownParser.renumberLists(value);\n      \n      if (newValue !== value) {\n        // Calculate cursor offset\n        let offset = 0;\n        const oldLines = value.split('\\n');\n        const newLines = newValue.split('\\n');\n        let charCount = 0;\n        \n        for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {\n          if (oldLines[i] !== newLines[i]) {\n            const diff = newLines[i].length - oldLines[i].length;\n            if (charCount + oldLines[i].length < cursorPos) {\n              offset += diff;\n            }\n          }\n          charCount += oldLines[i].length + 1; // +1 for newline\n        }\n        \n        // Update textarea\n        this.textarea.value = newValue;\n        const newCursorPos = cursorPos + offset;\n        this.textarea.setSelectionRange(newCursorPos, newCursorPos);\n        \n        // Trigger update\n        this.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n      }\n    }\n\n    /**\n     * Handle scroll events\n     * @private\n     */\n    handleScroll(event) {\n      // Sync preview scroll with textarea\n      this.preview.scrollTop = this.textarea.scrollTop;\n      this.preview.scrollLeft = this.textarea.scrollLeft;\n    }\n\n    /**\n     * Get editor content\n     * @returns {string} Current markdown content\n     */\n    getValue() {\n      return this.textarea.value;\n    }\n\n    /**\n     * Set editor content\n     * @param {string} value - Markdown content to set\n     */\n    setValue(value) {\n      this.textarea.value = value;\n      this.updatePreview();\n\n      // Update height if auto-resize is enabled\n      if (this.options.autoResize) {\n        this._updateAutoHeight();\n      }\n    }\n\n    /**\n     * Execute an action by ID\n     * Central dispatcher used by toolbar clicks, keyboard shortcuts, and programmatic calls\n     * @param {string} actionId - The action identifier (e.g., 'toggleBold', 'insertLink')\n     * @param {Event|null} event - Optional event that triggered the action\n     * @returns {Promise} Whether the action was executed successfully\n     */\n    async performAction(actionId, event = null) {\n      const textarea = this.textarea;\n      if (!textarea) return false;\n\n      const action = this.actionsById?.[actionId];\n      if (!action) {\n        console.warn(`OverType: Unknown action \"${actionId}\"`);\n        return false;\n      }\n\n      textarea.focus();\n\n      try {\n        await action({\n          editor: this,\n          getValue: () => this.getValue(),\n          setValue: (value) => this.setValue(value),\n          event\n        });\n        // Note: actions are responsible for dispatching input event\n        // This preserves behavior for direct consumers of toolbarButtons.*.action\n        return true;\n      } catch (error) {\n        console.error(`OverType: Action \"${actionId}\" error:`, error);\n        this.wrapper.dispatchEvent(new CustomEvent('button-error', {\n          detail: { actionId, error }\n        }));\n        return false;\n      }\n    }\n\n    /**\n     * Get the rendered HTML of the current content\n     * @param {Object} options - Rendering options\n     * @param {boolean} options.cleanHTML - If true, removes syntax markers and OverType-specific classes\n     * @returns {string} Rendered HTML\n     */\n    getRenderedHTML(options = {}) {\n      const markdown = this.getValue();\n      let html = MarkdownParser.parse(markdown, -1, false, this.options.codeHighlighter);\n\n      if (options.cleanHTML) {\n        // Remove all syntax marker spans for clean HTML export\n        html = html.replace(/.*?<\\/span>/g, '');\n        // Remove OverType-specific classes\n        html = html.replace(/\\sclass=\"(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)\"/g, '');\n        // Clean up empty class attributes\n        html = html.replace(/\\sclass=\"\"/g, '');\n      }\n      \n      return html;\n    }\n\n    /**\n     * Get the current preview element's HTML\n     * This includes all syntax markers and OverType styling\n     * @returns {string} Current preview HTML (as displayed)\n     */\n    getPreviewHTML() {\n      return this.preview.innerHTML;\n    }\n    \n    /**\n     * Get clean HTML without any OverType-specific markup\n     * Useful for exporting to other formats or storage\n     * @returns {string} Clean HTML suitable for export\n     */\n    getCleanHTML() {\n      return this.getRenderedHTML({ cleanHTML: true });\n    }\n\n    /**\n     * Focus the editor\n     */\n    focus() {\n      this.textarea.focus();\n    }\n\n    /**\n     * Blur the editor\n     */\n    blur() {\n      this.textarea.blur();\n    }\n\n    /**\n     * Check if editor is initialized\n     * @returns {boolean}\n     */\n    isInitialized() {\n      return this.initialized;\n    }\n\n    /**\n     * Re-initialize with new options\n     * @param {Object} options - New options to apply\n     */\n    reinit(options = {}) {\n      const prevToolbarButtons = this.options?.toolbarButtons;\n      this.options = this._mergeOptions({ ...this.options, ...options });\n      const toolbarNeedsRebuild = this.toolbar &&\n        this.options.toolbar &&\n        toolbarButtonsChanged(prevToolbarButtons, this.options.toolbarButtons);\n\n      // Rebuild action map in case toolbarButtons changed\n      this._rebuildActionsMap();\n\n      if (toolbarNeedsRebuild) {\n        this._cleanupToolbarListeners();\n        this.toolbar.destroy();\n        this.toolbar = null;\n        this._createToolbar();\n      }\n\n      this._applyOptions();\n      this.updatePreview();\n    }\n\n    /**\n     * Set theme for this instance\n     * @param {string|Object} theme - Theme name or custom theme object\n     * @returns {this} Returns this for chaining\n     */\n    setTheme(theme) {\n      this._cleanupAuto();\n      this.instanceTheme = theme;\n\n      if (theme === 'auto') {\n        this._setupAuto();\n        this._applyTheme(resolveAutoTheme('auto'));\n      } else {\n        const themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n        const themeName = themeObj.name || theme;\n\n        if (themeName) {\n          this.container.setAttribute('data-theme', themeName);\n        }\n\n        if (themeObj?.colors) {\n          this.container.style.cssText += themeToCSSVars(themeObj.colors);\n        }\n\n        this.updatePreview();\n      }\n\n      return this;\n    }\n\n    /**\n     * Apply a resolved theme name (used by auto theme)\n     * @private\n     */\n    _applyTheme(themeName) {\n      const themeObj = getTheme(themeName);\n      this.container.setAttribute('data-theme', 'auto');\n      this.container.setAttribute('data-resolved-theme', themeName);\n\n      if (themeObj?.colors) {\n        this.container.style.cssText += themeToCSSVars(themeObj.colors);\n      }\n\n      this.updatePreview();\n    }\n\n    /**\n     * Setup auto theme listener for instance\n     * @private\n     */\n    _setupAuto() {\n      if (!window.matchMedia) return;\n\n      OverType._autoInstances.add(this);\n\n      if (!OverType._mq) {\n        OverType._mq = window.matchMedia('(prefers-color-scheme: dark)');\n        OverType._mqListener = (e) => {\n          const theme = e.matches ? 'cave' : 'solar';\n          OverType._autoInstances.forEach(inst => inst._applyTheme(theme));\n        };\n        \n        // Use modern addEventListener or fallback to legacy addListener\n        (OverType._mq.addEventListener || OverType._mq.addListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n      }\n    }\n\n    /**\n     * Clean up auto theme listener for instance\n     * @private\n     */\n    _cleanupAuto() {\n      OverType._autoInstances.delete(this);\n\n      if (OverType._autoInstances.size === 0 && OverType._mq) {\n        // Use modern removeEventListener or fallback to legacy removeListener\n        (OverType._mq.removeEventListener || OverType._mq.removeListener)?.call(\n          OverType._mq, 'change', OverType._mqListener\n        );\n        OverType._mq = null;\n        OverType._mqListener = null;\n      }\n    }\n\n    /**\n     * Set instance-specific code highlighter\n     * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n     */\n    setCodeHighlighter(highlighter) {\n      this.options.codeHighlighter = highlighter;\n      this.updatePreview();\n    }\n\n    /**\n     * Update stats bar\n     * @private\n     */\n    _updateStats() {\n      if (!this.statsBar) return;\n      \n      const value = this.textarea.value;\n      const lines = value.split('\\n');\n      const chars = value.length;\n      const words = value.split(/\\s+/).filter(w => w.length > 0).length;\n      \n      // Calculate line and column\n      const selectionStart = this.textarea.selectionStart;\n      const beforeCursor = value.substring(0, selectionStart);\n      const linesBeforeCursor = beforeCursor.split('\\n');\n      const currentLine = linesBeforeCursor.length;\n      const currentColumn = linesBeforeCursor[linesBeforeCursor.length - 1].length + 1;\n      \n      // Use custom formatter if provided\n      if (this.options.statsFormatter) {\n        this.statsBar.innerHTML = this.options.statsFormatter({\n          chars,\n          words,\n          lines: lines.length,\n          line: currentLine,\n          column: currentColumn\n        });\n      } else {\n        // Default format with live dot\n        this.statsBar.innerHTML = `\n          
    \n \n ${chars} chars, ${words} words, ${lines.length} lines\n
    \n
    Line ${currentLine}, Col ${currentColumn}
    \n `;\n }\n }\n \n /**\n * Setup auto-resize functionality\n * @private\n */\n _setupAutoResize() {\n // Add auto-resize class for styling\n this.container.classList.add('overtype-auto-resize');\n \n // Store previous height for comparison\n this.previousHeight = null;\n \n // Initial height update\n this._updateAutoHeight();\n \n // Listen for input events\n this.textarea.addEventListener('input', () => this._updateAutoHeight());\n \n // Listen for window resize\n window.addEventListener('resize', () => this._updateAutoHeight());\n }\n \n /**\n * Update height based on scrollHeight\n * @private\n */\n _updateAutoHeight() {\n if (!this.options.autoResize) return;\n \n const textarea = this.textarea;\n const preview = this.preview;\n const wrapper = this.wrapper;\n \n // Get computed styles\n const computed = window.getComputedStyle(textarea);\n const paddingTop = parseFloat(computed.paddingTop);\n const paddingBottom = parseFloat(computed.paddingBottom);\n \n // Store scroll positions\n const scrollTop = textarea.scrollTop;\n \n // Reset height to get accurate scrollHeight\n textarea.style.setProperty('height', 'auto', 'important');\n \n // Calculate new height based on scrollHeight\n let newHeight = textarea.scrollHeight;\n \n // Apply min height constraint\n if (this.options.minHeight) {\n const minHeight = parseInt(this.options.minHeight);\n newHeight = Math.max(newHeight, minHeight);\n }\n \n // Apply max height constraint\n let overflow = 'hidden';\n if (this.options.maxHeight) {\n const maxHeight = parseInt(this.options.maxHeight);\n if (newHeight > maxHeight) {\n newHeight = maxHeight;\n overflow = 'auto';\n }\n }\n \n // Apply the new height to all elements with !important to override base styles\n const heightPx = newHeight + 'px';\n textarea.style.setProperty('height', heightPx, 'important');\n textarea.style.setProperty('overflow-y', overflow, 'important');\n \n preview.style.setProperty('height', heightPx, 'important');\n preview.style.setProperty('overflow-y', overflow, 'important');\n \n wrapper.style.setProperty('height', heightPx, 'important');\n \n // Restore scroll position\n textarea.scrollTop = scrollTop;\n preview.scrollTop = scrollTop;\n \n // Track if height changed\n if (this.previousHeight !== newHeight) {\n this.previousHeight = newHeight;\n // Could dispatch a custom event here if needed\n }\n }\n \n /**\n * Show or hide stats bar\n * @param {boolean} show - Whether to show stats\n */\n showStats(show) {\n this.options.showStats = show;\n\n if (show && !this.statsBar) {\n // Create stats bar (add to container, not wrapper)\n this.statsBar = document.createElement('div');\n this.statsBar.className = 'overtype-stats';\n this.container.appendChild(this.statsBar);\n this._updateStats();\n } else if (show && this.statsBar) {\n // Already visible - refresh stats (useful after changing statsFormatter)\n this._updateStats();\n } else if (!show && this.statsBar) {\n // Remove stats bar\n this.statsBar.remove();\n this.statsBar = null;\n }\n }\n \n /**\n * Show normal edit mode (overlay with markdown preview)\n * @returns {this} Returns this for chaining\n */\n showNormalEditMode() {\n this.container.dataset.mode = 'normal';\n this.updatePreview(); // Re-render with normal mode (e.g., show syntax markers)\n\n // Always sync scroll from preview to textarea\n requestAnimationFrame(() => {\n this.textarea.scrollTop = this.preview.scrollTop;\n this.textarea.scrollLeft = this.preview.scrollLeft;\n });\n\n return this;\n }\n\n /**\n * Show plain textarea mode (no overlay)\n * @returns {this} Returns this for chaining\n */\n showPlainTextarea() {\n this.container.dataset.mode = 'plain';\n\n // Update toolbar button if exists\n if (this.toolbar) {\n const toggleBtn = this.container.querySelector('[data-action=\"toggle-plain\"]');\n if (toggleBtn) {\n toggleBtn.classList.remove('active');\n toggleBtn.title = 'Show markdown preview';\n }\n }\n\n return this;\n }\n\n /**\n * Show preview mode (read-only view)\n * @returns {this} Returns this for chaining\n */\n showPreviewMode() {\n this.container.dataset.mode = 'preview';\n this.updatePreview(); // Re-render with preview mode (e.g., checkboxes)\n return this;\n }\n\n /**\n * Destroy the editor instance\n */\n destroy() {\n // Clean up auto theme listener\n this._cleanupAuto();\n\n // Remove instance reference\n this.element.overTypeInstance = null;\n OverType.instances.delete(this.element);\n\n // Cleanup shortcuts\n if (this.shortcuts) {\n this.shortcuts.destroy();\n }\n\n // Remove DOM if created by us\n if (this.wrapper) {\n const content = this.getValue();\n this.wrapper.remove();\n \n // Restore original content\n this.element.textContent = content;\n }\n\n this.initialized = false;\n }\n\n // ===== Static Methods =====\n\n /**\n * Initialize multiple editors (static convenience method)\n * @param {string|Element|NodeList|Array} target - Target element(s)\n * @param {Object} options - Configuration options\n * @returns {Array} Array of OverType instances\n */\n static init(target, options = {}) {\n return new OverType(target, options);\n }\n\n /**\n * Initialize editors with options from data-ot-* attributes\n * @param {string} selector - CSS selector for target elements\n * @param {Object} defaults - Default options (data attrs override these)\n * @returns {Array} Array of OverType instances\n * @example\n * // HTML:
    \n * OverType.initFromData('.editor', { fontSize: '14px' });\n */\n static initFromData(selector, defaults = {}) {\n const elements = document.querySelectorAll(selector);\n return Array.from(elements).map(el => {\n const options = { ...defaults };\n\n // Parse data-ot-* attributes (kebab-case to camelCase)\n for (const attr of el.attributes) {\n if (attr.name.startsWith('data-ot-')) {\n const kebab = attr.name.slice(8); // Remove 'data-ot-'\n const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n options[key] = OverType._parseDataValue(attr.value);\n }\n }\n\n return new OverType(el, options);\n });\n }\n\n /**\n * Parse a data attribute value to the appropriate type\n * @private\n */\n static _parseDataValue(value) {\n if (value === 'true') return true;\n if (value === 'false') return false;\n if (value === 'null') return null;\n if (value !== '' && !isNaN(Number(value))) return Number(value);\n return value;\n }\n\n /**\n * Get instance from element\n * @param {Element} element - DOM element\n * @returns {OverType|null} OverType instance or null\n */\n static getInstance(element) {\n return element.overTypeInstance || OverType.instances.get(element) || null;\n }\n\n /**\n * Destroy all instances\n */\n static destroyAll() {\n const elements = document.querySelectorAll('[data-overtype-instance]');\n elements.forEach(element => {\n const instance = OverType.getInstance(element);\n if (instance) {\n instance.destroy();\n }\n });\n }\n\n /**\n * Inject styles into the document\n * @param {boolean} force - Force re-injection\n */\n static injectStyles(force = false) {\n if (OverType.stylesInjected && !force) return;\n\n // Remove any existing OverType styles\n const existing = document.querySelector('style.overtype-styles');\n if (existing) {\n existing.remove();\n }\n\n // Generate and inject new styles with current theme\n const theme = OverType.currentTheme || solar;\n const styles = generateStyles({ theme });\n const styleEl = document.createElement('style');\n styleEl.className = 'overtype-styles';\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n\n OverType.stylesInjected = true;\n }\n \n /**\n * Helper to update DOM elements with theme attributes\n * @private\n */\n static _updateThemeAttrs(themeName, isAuto = false) {\n const setTheme = (el) => {\n if (isAuto) {\n el.setAttribute('data-theme', 'auto');\n el.setAttribute('data-resolved-theme', themeName);\n } else {\n el.setAttribute('data-theme', themeName);\n }\n };\n \n document.querySelectorAll('.overtype-container').forEach(setTheme);\n \n document.querySelectorAll('.overtype-wrapper').forEach(w => {\n if (!w.closest('.overtype-container')) setTheme(w);\n w._instance?.updatePreview();\n });\n \n document.querySelectorAll('overtype-editor').forEach(wc => {\n wc.setAttribute?.('theme', isAuto ? 'auto' : themeName);\n if (isAuto) wc.setAttribute?.('data-resolved-theme', themeName);\n wc.refreshTheme?.();\n });\n }\n \n /**\n * Set global theme for all OverType instances\n * @param {string|Object} theme - Theme name or custom theme object\n * @param {Object} customColors - Optional color overrides\n */\n static setTheme(theme, customColors = null) {\n // Clean up existing auto theme listener\n OverType._cleanupGlobalAuto();\n\n // Handle auto theme at global level\n if (theme === 'auto') {\n OverType._setupGlobalAuto();\n OverType._applyGlobalTheme(resolveAutoTheme('auto'), customColors, true);\n } else {\n // Process theme\n let themeObj = typeof theme === 'string' ? getTheme(theme) : theme;\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all existing instances\n const themeName = themeObj.name || theme;\n if (themeName) {\n OverType._updateThemeAttrs(themeName);\n }\n }\n }\n\n /**\n * Apply a resolved theme globally (used by auto theme)\n * @private\n * @param {string} themeName - Resolved theme name\n * @param {Object} customColors - Optional color overrides\n * @param {boolean} isAuto - Whether this is an auto theme\n */\n static _applyGlobalTheme(themeName, customColors = null, isAuto = false) {\n let themeObj = getTheme(themeName);\n\n // Apply custom colors if provided\n if (customColors) {\n themeObj = mergeTheme(themeObj, customColors);\n }\n\n // Store as current theme\n OverType.currentTheme = themeObj;\n\n // Re-inject styles with new theme\n OverType.injectStyles(true);\n\n // Update all elements\n OverType._updateThemeAttrs(themeName, isAuto);\n }\n\n /**\n * Setup global auto theme listener\n * @private\n */\n static _setupGlobalAuto() {\n if (!window.matchMedia || OverType._globalAutoMq) return;\n\n OverType._globalAutoMq = window.matchMedia('(prefers-color-scheme: dark)');\n OverType._globalAutoListener = (e) => {\n OverType._applyGlobalTheme(e.matches ? 'cave' : 'solar', null, true);\n };\n\n // Use modern addEventListener or fallback to legacy addListener\n (OverType._globalAutoMq.addEventListener || OverType._globalAutoMq.addListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n }\n\n /**\n * Clean up global auto theme listener\n * @private\n */\n static _cleanupGlobalAuto() {\n if (OverType._globalAutoMq && OverType._globalAutoListener) {\n // Use modern removeEventListener or fallback to legacy removeListener\n (OverType._globalAutoMq.removeEventListener || OverType._globalAutoMq.removeListener)?.call(\n OverType._globalAutoMq, 'change', OverType._globalAutoListener\n );\n OverType._globalAutoMq = null;\n OverType._globalAutoListener = null;\n }\n }\n\n /**\n * Set global code highlighter for all OverType instances\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n MarkdownParser.setCodeHighlighter(highlighter);\n\n // Update all existing instances in light DOM\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n // Update web components (shadow DOM instances)\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Set custom syntax processor for extending markdown parsing\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n * @example\n * OverType.setCustomSyntax((html) => {\n * // Highlight footnote references [^1]\n * return html.replace(/\\[\\^(\\w+)\\]/g, '$&');\n * });\n */\n static setCustomSyntax(processor) {\n MarkdownParser.setCustomSyntax(processor);\n\n // Update all existing instances\n document.querySelectorAll('.overtype-wrapper').forEach(wrapper => {\n const instance = wrapper._instance;\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n });\n\n document.querySelectorAll('overtype-editor').forEach(webComponent => {\n if (typeof webComponent.getEditor === 'function') {\n const instance = webComponent.getEditor();\n if (instance && instance.updatePreview) {\n instance.updatePreview();\n }\n }\n });\n }\n\n /**\n * Initialize global event listeners\n */\n static initGlobalListeners() {\n if (OverType.globalListenersInitialized) return;\n\n // Input event\n document.addEventListener('input', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleInput(e);\n }\n });\n\n // Keydown event\n document.addEventListener('keydown', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleKeydown(e);\n }\n });\n\n // Scroll event\n document.addEventListener('scroll', (e) => {\n if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {\n const wrapper = e.target.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) instance.handleScroll(e);\n }\n }, true);\n\n // Selection change event\n document.addEventListener('selectionchange', (e) => {\n const activeElement = document.activeElement;\n if (activeElement && activeElement.classList.contains('overtype-input')) {\n const wrapper = activeElement.closest('.overtype-wrapper');\n const instance = wrapper?._instance;\n if (instance) {\n // Update stats bar for cursor position\n if (instance.options.showStats && instance.statsBar) {\n instance._updateStats();\n }\n // Debounce updates\n clearTimeout(instance._selectionTimeout);\n instance._selectionTimeout = setTimeout(() => {\n instance.updatePreview();\n }, 50);\n }\n }\n });\n\n OverType.globalListenersInitialized = true;\n }\n}\n\n// Export classes for advanced usage\nOverType.MarkdownParser = MarkdownParser;\nOverType.ShortcutsManager = ShortcutsManager;\n\n// Export theme utilities\nOverType.themes = { solar, cave: getTheme('cave') };\nOverType.getTheme = getTheme;\n\n// Set default theme\nOverType.currentTheme = solar;\n\n// Export for module systems\nexport default OverType;\nexport { OverType };\n\n// Export toolbar buttons for custom toolbar configurations\nexport { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';\n", "/**\n * MarkdownParser - Parses markdown into HTML while preserving character alignment\n *\n * Key principles:\n * - Every character must occupy the exact same position as in the textarea\n * - No font-size changes, no padding/margin on inline elements\n * - Markdown tokens remain visible but styled\n */\nexport class MarkdownParser {\n // Track link index for anchor naming\n static linkIndex = 0;\n\n // Global code highlighter function\n static codeHighlighter = null;\n\n // Custom syntax processor function\n static customSyntax = null;\n\n /**\n * Reset link index (call before parsing a new document)\n */\n static resetLinkIndex() {\n this.linkIndex = 0;\n }\n\n /**\n * Set global code highlighter function\n * @param {Function|null} highlighter - Function that takes (code, language) and returns highlighted HTML\n */\n static setCodeHighlighter(highlighter) {\n this.codeHighlighter = highlighter;\n }\n\n /**\n * Set custom syntax processor function\n * @param {Function|null} processor - Function that takes (html) and returns modified HTML\n */\n static setCustomSyntax(processor) {\n this.customSyntax = processor;\n }\n\n /**\n * Apply custom syntax processor to parsed HTML\n * @param {string} html - Parsed HTML line\n * @returns {string} HTML with custom syntax applied\n */\n static applyCustomSyntax(html) {\n if (this.customSyntax) {\n return this.customSyntax(html);\n }\n return html;\n }\n\n /**\n * Escape HTML special characters\n * @param {string} text - Raw text to escape\n * @returns {string} Escaped HTML-safe text\n */\n static escapeHtml(text) {\n const map = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n };\n return text.replace(/[&<>\"']/g, m => map[m]);\n }\n\n /**\n * Preserve leading spaces as non-breaking spaces\n * @param {string} html - HTML string\n * @param {string} originalLine - Original line with spaces\n * @returns {string} HTML with preserved indentation\n */\n static preserveIndentation(html, originalLine) {\n const leadingSpaces = originalLine.match(/^(\\s*)/)[1];\n const indentation = leadingSpaces.replace(/ /g, ' ');\n return html.replace(/^\\s*/, indentation);\n }\n\n /**\n * Parse headers (h1-h3 only)\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed HTML with header styling\n */\n static parseHeader(html) {\n return html.replace(/^(#{1,3})\\s(.+)$/, (match, hashes, content) => {\n const level = hashes.length;\n return `${hashes} ${content}`;\n });\n }\n\n /**\n * Parse horizontal rules\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed horizontal rule or null\n */\n static parseHorizontalRule(html) {\n if (html.match(/^(-{3,}|\\*{3,}|_{3,})$/)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse blockquotes\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed blockquote\n */\n static parseBlockquote(html) {\n return html.replace(/^> (.+)$/, (match, content) => {\n return `> ${content}`;\n });\n }\n\n /**\n * Parse bullet lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed bullet list item\n */\n static parseBulletList(html) {\n return html.replace(/^((?: )*)([-*+])\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse task lists (GitHub Flavored Markdown checkboxes)\n * @param {string} html - HTML line to parse\n * @param {boolean} isPreviewMode - Whether to render actual checkboxes (preview) or keep syntax visible (normal)\n * @returns {string} Parsed task list item\n */\n static parseTaskList(html, isPreviewMode = false) {\n return html.replace(/^((?: )*)-\\s+\\[([ xX])\\]\\s+(.+)$/, (match, indent, checked, content) => {\n if (isPreviewMode) {\n // Preview mode: render actual checkbox\n const isChecked = checked.toLowerCase() === 'x';\n return `${indent}
  • ${content}
  • `;\n } else {\n // Normal mode: keep syntax visible for alignment\n return `${indent}
  • - [${checked}] ${content}
  • `;\n }\n });\n }\n\n /**\n * Parse numbered lists\n * @param {string} html - HTML line to parse\n * @returns {string} Parsed numbered list item\n */\n static parseNumberedList(html) {\n return html.replace(/^((?: )*)(\\d+\\.)\\s(.+)$/, (match, indent, marker, content) => {\n return `${indent}
  • ${marker} ${content}
  • `;\n });\n }\n\n /**\n * Parse code blocks (markers only)\n * @param {string} html - HTML line to parse\n * @returns {string|null} Parsed code fence or null\n */\n static parseCodeBlock(html) {\n // The line must start with three backticks and have no backticks after subsequent text\n const codeFenceRegex = /^`{3}[^`]*$/;\n if (codeFenceRegex.test(html)) {\n return `
    ${html}
    `;\n }\n return null;\n }\n\n /**\n * Parse bold text\n * @param {string} html - HTML with potential bold markdown\n * @returns {string} HTML with bold styling\n */\n static parseBold(html) {\n html = html.replace(/\\*\\*(.+?)\\*\\*/g, '**$1**');\n html = html.replace(/__(.+?)__/g, '__$1__');\n return html;\n }\n\n /**\n * Parse italic text\n * Note: Uses lookbehind assertions - requires modern browsers\n * @param {string} html - HTML with potential italic markdown\n * @returns {string} HTML with italic styling\n */\n static parseItalic(html) {\n // Single asterisk - must not be adjacent to other asterisks\n // Also must not be inside a syntax-marker span (to avoid matching bullet list markers)\n html = html.replace(/(?])\\*(?!\\*)(.+?)(?*$1*');\n\n // Single underscore - must be at word boundaries to avoid matching inside words\n // This prevents matching underscores in the middle of words like \"bold_with_underscore\"\n html = html.replace(/(?<=^|\\s)_(?!_)(.+?)(?_$1_');\n\n return html;\n }\n\n /**\n * Parse strikethrough text\n * Supports both single (~) and double (~~) tildes, but rejects 3+ tildes\n * @param {string} html - HTML with potential strikethrough markdown\n * @returns {string} HTML with strikethrough styling\n */\n static parseStrikethrough(html) {\n // Double tilde strikethrough: ~~text~~ (but not if part of 3+ tildes)\n html = html.replace(/(?~~$1~~');\n // Single tilde strikethrough: ~text~ (but not if part of 2+ tildes on either side)\n html = html.replace(/(?~$1~');\n return html;\n }\n\n /**\n * Parse inline code\n * @param {string} html - HTML with potential code markdown\n * @returns {string} HTML with code styling\n */\n static parseInlineCode(html) {\n // Must have equal number of backticks before and after inline code\n //\n // Regex explainer:\n // (?$1$2$3
    ');\n }\n\n /**\n * Sanitize URL to prevent XSS attacks\n * @param {string} url - URL to sanitize\n * @returns {string} Safe URL or '#' if dangerous\n */\n static sanitizeUrl(url) {\n // Trim whitespace and convert to lowercase for protocol check\n const trimmed = url.trim();\n const lower = trimmed.toLowerCase();\n\n // Allow safe protocols\n const safeProtocols = [\n 'http://',\n 'https://',\n 'mailto:',\n 'ftp://',\n 'ftps://'\n ];\n\n // Check if URL starts with a safe protocol\n const hasSafeProtocol = safeProtocols.some(protocol => lower.startsWith(protocol));\n\n // Allow relative URLs (starting with / or # or no protocol)\n const isRelative = trimmed.startsWith('/') ||\n trimmed.startsWith('#') ||\n trimmed.startsWith('?') ||\n trimmed.startsWith('.') ||\n (!trimmed.includes(':') && !trimmed.includes('//'));\n\n // If safe protocol or relative URL, return as-is\n if (hasSafeProtocol || isRelative) {\n return url;\n }\n\n // Block dangerous protocols (javascript:, data:, vbscript:, etc.)\n return '#';\n }\n\n /**\n * Parse links\n * @param {string} html - HTML with potential link markdown\n * @returns {string} HTML with link styling\n */\n static parseLinks(html) {\n return html.replace(/\\[(.+?)\\]\\((.+?)\\)/g, (match, text, url) => {\n const anchorName = `--link-${this.linkIndex++}`;\n // Sanitize URL to prevent XSS attacks\n const safeUrl = this.sanitizeUrl(url);\n // Use real href - pointer-events handles click prevention in normal mode\n return `
    [${text}](${url})`;\n });\n }\n\n /**\n * Identify and protect sanctuaries (code and links) before parsing\n * @param {string} text - Text with potential markdown\n * @returns {Object} Object with protected text and sanctuary map\n */\n static identifyAndProtectSanctuaries(text) {\n const sanctuaries = new Map();\n let sanctuaryCounter = 0;\n let protectedText = text;\n \n // Create a map to track protected regions (URLs should not be processed)\n const protectedRegions = [];\n \n // First, find all links and mark their URL regions as protected\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let linkMatch;\n while ((linkMatch = linkRegex.exec(text)) !== null) {\n // Calculate the exact position of the URL part\n // linkMatch.index is the start of the match\n // We need to find where \"](\" starts, then add 2 to get URL start\n const bracketPos = linkMatch.index + linkMatch[0].indexOf('](');\n const urlStart = bracketPos + 2;\n const urlEnd = urlStart + linkMatch[2].length;\n protectedRegions.push({ start: urlStart, end: urlEnd });\n }\n \n // Now protect inline code, but skip if it's inside a protected region (URL)\n const codeRegex = /(? \n codeStart >= region.start && codeEnd <= region.end\n );\n \n if (!inProtectedRegion) {\n codeMatches.push({\n match: codeMatch[0],\n index: codeMatch.index,\n openTicks: codeMatch[1],\n content: codeMatch[2],\n closeTicks: codeMatch[3]\n });\n }\n }\n \n // Replace code matches from end to start to preserve indices\n codeMatches.sort((a, b) => b.index - a.index);\n codeMatches.forEach(codeInfo => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'code',\n original: codeInfo.match,\n openTicks: codeInfo.openTicks,\n content: codeInfo.content,\n closeTicks: codeInfo.closeTicks\n });\n protectedText = protectedText.substring(0, codeInfo.index) + \n placeholder + \n protectedText.substring(codeInfo.index + codeInfo.match.length);\n });\n \n // Then protect links - they can contain sanctuary placeholders for code but not raw code\n protectedText = protectedText.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (match, linkText, url) => {\n const placeholder = `\\uE000${sanctuaryCounter++}\\uE001`;\n sanctuaries.set(placeholder, {\n type: 'link',\n original: match,\n linkText,\n url\n });\n return placeholder;\n });\n \n return { protectedText, sanctuaries };\n }\n \n /**\n * Restore and transform sanctuaries back to HTML\n * @param {string} html - HTML with sanctuary placeholders\n * @param {Map} sanctuaries - Map of sanctuaries to restore\n * @returns {string} HTML with sanctuaries restored and transformed\n */\n static restoreAndTransformSanctuaries(html, sanctuaries) {\n // Sort sanctuary placeholders by position to restore in order\n const placeholders = Array.from(sanctuaries.keys()).sort((a, b) => {\n const indexA = html.indexOf(a);\n const indexB = html.indexOf(b);\n return indexA - indexB;\n });\n \n placeholders.forEach(placeholder => {\n const sanctuary = sanctuaries.get(placeholder);\n let replacement;\n \n if (sanctuary.type === 'code') {\n // Transform code sanctuary to HTML\n replacement = `${sanctuary.openTicks}${sanctuary.content}${sanctuary.closeTicks}`;\n } else if (sanctuary.type === 'link') {\n // For links, we need to process the link text for markdown\n let processedLinkText = sanctuary.linkText;\n \n // First restore any sanctuary placeholders that were already in the link text\n // (e.g., inline code that was protected before the link)\n sanctuaries.forEach((innerSanctuary, innerPlaceholder) => {\n if (processedLinkText.includes(innerPlaceholder)) {\n if (innerSanctuary.type === 'code') {\n const codeHtml = `${innerSanctuary.openTicks}${innerSanctuary.content}${innerSanctuary.closeTicks}`;\n processedLinkText = processedLinkText.replace(innerPlaceholder, codeHtml);\n }\n }\n });\n \n // Now parse other markdown in the link text (bold, italic, etc)\n processedLinkText = this.parseStrikethrough(processedLinkText);\n processedLinkText = this.parseBold(processedLinkText);\n processedLinkText = this.parseItalic(processedLinkText);\n \n // Transform link sanctuary to HTML\n // URL should NOT be processed for markdown - use it as-is\n const anchorName = `--link-${this.linkIndex++}`;\n const safeUrl = this.sanitizeUrl(sanctuary.url);\n replacement = `[${processedLinkText}](${sanctuary.url})`;\n }\n \n html = html.replace(placeholder, replacement);\n });\n \n return html;\n }\n \n /**\n * Parse all inline elements in correct order\n * @param {string} text - Text with potential inline markdown\n * @returns {string} HTML with all inline styling\n */\n static parseInlineElements(text) {\n // Step 1: Identify and protect sanctuaries (code and links)\n const { protectedText, sanctuaries } = this.identifyAndProtectSanctuaries(text);\n \n // Step 2: Parse other inline elements on protected text\n let html = protectedText;\n html = this.parseStrikethrough(html);\n html = this.parseBold(html);\n html = this.parseItalic(html);\n \n // Step 3: Restore and transform sanctuaries\n html = this.restoreAndTransformSanctuaries(html, sanctuaries);\n \n return html;\n }\n\n /**\n * Parse a single line of markdown\n * @param {string} line - Raw markdown line\n * @returns {string} Parsed HTML line\n */\n static parseLine(line, isPreviewMode = false) {\n let html = this.escapeHtml(line);\n\n // Preserve indentation\n html = this.preserveIndentation(html, line);\n\n // Check for block elements first\n const horizontalRule = this.parseHorizontalRule(html);\n if (horizontalRule) return horizontalRule;\n\n const codeBlock = this.parseCodeBlock(html);\n if (codeBlock) return codeBlock;\n\n // Parse block elements\n html = this.parseHeader(html);\n html = this.parseBlockquote(html);\n html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists\n html = this.parseBulletList(html);\n html = this.parseNumberedList(html);\n\n // Parse inline elements\n html = this.parseInlineElements(html);\n\n // Wrap in div to maintain line structure\n if (html.trim() === '') {\n // Intentionally use   for empty lines to maintain vertical spacing\n // This causes a 0->1 character count difference but preserves visual alignment\n return '
     
    ';\n }\n\n return `
    ${html}
    `;\n }\n\n /**\n * Parse full markdown text\n * @param {string} text - Full markdown text\n * @param {number} activeLine - Currently active line index (optional)\n * @param {boolean} showActiveLineRaw - Show raw markdown on active line\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Parsed HTML\n */\n static parse(text, activeLine = -1, showActiveLineRaw = false, instanceHighlighter, isPreviewMode = false) {\n // Reset link counter for each parse\n this.resetLinkIndex();\n\n const lines = text.split('\\n');\n let inCodeBlock = false;\n\n const parsedLines = lines.map((line, index) => {\n // Show raw markdown on active line if requested\n if (showActiveLineRaw && index === activeLine) {\n const content = this.escapeHtml(line) || ' ';\n return `
    ${content}
    `;\n }\n\n // Check if this line is a code fence\n const codeFenceRegex = /^```[^`]*$/;\n if (codeFenceRegex.test(line)) {\n inCodeBlock = !inCodeBlock;\n // Parse fence markers normally to get styled output\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n }\n\n // If we're inside a code block, don't parse as markdown\n if (inCodeBlock) {\n const escaped = this.escapeHtml(line);\n const indented = this.preserveIndentation(escaped, line);\n return `
    ${indented || ' '}
    `;\n }\n\n // Otherwise, parse the markdown normally\n return this.applyCustomSyntax(this.parseLine(line, isPreviewMode));\n });\n\n // Join without newlines to prevent extra spacing\n const html = parsedLines.join('');\n\n // Apply post-processing for list consolidation\n return this.postProcessHTML(html, instanceHighlighter);\n }\n\n /**\n * Post-process HTML to consolidate lists and code blocks\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML with consolidated lists and code blocks\n */\n static postProcessHTML(html, instanceHighlighter) {\n // Check if we're in a browser environment\n if (typeof document === 'undefined' || !document) {\n // In Node.js environment - do manual post-processing\n return this.postProcessHTMLManual(html, instanceHighlighter);\n }\n\n // Parse HTML string into DOM\n const container = document.createElement('div');\n container.innerHTML = html;\n\n let currentList = null;\n let listType = null;\n let currentCodeBlock = null;\n let inCodeBlock = false;\n\n // Process all direct children - need to be careful with live NodeList\n const children = Array.from(container.children);\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Skip if child was already processed/removed\n if (!child.parentNode) continue;\n\n // Check for code fence start/end\n const codeFence = child.querySelector('.code-fence');\n if (codeFence) {\n const fenceText = codeFence.textContent;\n if (fenceText.startsWith('```')) {\n if (!inCodeBlock) {\n // Start of code block - keep fence visible, then add pre/code\n inCodeBlock = true;\n\n // Create the code block that will follow the fence\n currentCodeBlock = document.createElement('pre');\n const codeElement = document.createElement('code');\n currentCodeBlock.appendChild(codeElement);\n currentCodeBlock.className = 'code-block';\n\n // Extract language if present\n const lang = fenceText.slice(3).trim();\n if (lang) {\n codeElement.className = `language-${lang}`;\n }\n\n // Insert code block after the fence div (don't remove the fence)\n container.insertBefore(currentCodeBlock, child.nextSibling);\n\n // Store reference to the code element for adding content\n currentCodeBlock._codeElement = codeElement;\n currentCodeBlock._language = lang;\n currentCodeBlock._codeContent = '';\n continue;\n } else {\n // End of code block - apply highlighting if needed\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (currentCodeBlock && highlighter && currentCodeBlock._codeContent) {\n try {\n const result = highlighter(\n currentCodeBlock._codeContent,\n currentCodeBlock._language || ''\n );\n\n // Check if result is a Promise (async highlighter)\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in parse() because it returns an HTML string. The caller creates new DOM elements from that string, breaking references to the elements we would update. Use synchronous highlighters only.');\n // Keep the plain text fallback that was already set\n } else {\n // Synchronous highlighter\n // Verify highlighter returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n currentCodeBlock._codeElement.innerHTML = result;\n }\n // else: keep the plain text fallback that was already set\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Keep the plain text content as fallback\n }\n }\n\n inCodeBlock = false;\n currentCodeBlock = null;\n continue;\n }\n }\n }\n\n // Check if we're in a code block - any div that's not a code fence\n if (inCodeBlock && currentCodeBlock && child.tagName === 'DIV' && !child.querySelector('.code-fence')) {\n const codeElement = currentCodeBlock._codeElement || currentCodeBlock.querySelector('code');\n // Add the line content to the code block content (for highlighting)\n if (currentCodeBlock._codeContent.length > 0) {\n currentCodeBlock._codeContent += '\\n';\n }\n // Get the actual text content, preserving spaces\n const lineText = child.textContent.replace(/\\u00A0/g, ' '); // \\u00A0 is nbsp\n currentCodeBlock._codeContent += lineText;\n\n // Also add to the code element (fallback if no highlighter)\n if (codeElement.textContent.length > 0) {\n codeElement.textContent += '\\n';\n }\n codeElement.textContent += lineText;\n child.remove();\n continue;\n }\n\n // Check if this div contains a list item\n let listItem = null;\n if (child.tagName === 'DIV') {\n // Look for li inside the div\n listItem = child.querySelector('li');\n }\n\n if (listItem) {\n const isBullet = listItem.classList.contains('bullet-list');\n const isOrdered = listItem.classList.contains('ordered-list');\n\n if (!isBullet && !isOrdered) {\n currentList = null;\n listType = null;\n continue;\n }\n\n const newType = isBullet ? 'ul' : 'ol';\n\n // Start new list or continue current\n if (!currentList || listType !== newType) {\n currentList = document.createElement(newType);\n container.insertBefore(currentList, child);\n listType = newType;\n }\n\n // Extract and preserve indentation from the div before moving the list item\n const indentationNodes = [];\n for (const node of child.childNodes) {\n if (node.nodeType === 3 && node.textContent.match(/^\\u00A0+$/)) {\n // This is a text node containing only non-breaking spaces (indentation)\n indentationNodes.push(node.cloneNode(true));\n } else if (node === listItem) {\n break; // Stop when we reach the list item\n }\n }\n\n // Add indentation to the list item\n indentationNodes.forEach(node => {\n listItem.insertBefore(node, listItem.firstChild);\n });\n\n // Move the list item to the current list\n currentList.appendChild(listItem);\n\n // Remove the now-empty div wrapper\n child.remove();\n } else {\n // Non-list element ends current list\n currentList = null;\n listType = null;\n }\n }\n\n return container.innerHTML;\n }\n\n /**\n * Manual post-processing for Node.js environments (without DOM)\n * @param {string} html - HTML to post-process\n * @param {Function} instanceHighlighter - Instance-specific code highlighter (optional, overrides global if provided)\n * @returns {string} Post-processed HTML\n */\n static postProcessHTMLManual(html, instanceHighlighter) {\n let processed = html;\n\n // Process unordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process ordered lists\n processed = processed.replace(/((?:
    (?: )*
  • .*?<\\/li><\\/div>\\s*)+)/gs, (match) => {\n const divs = match.match(/
    (?: )*
  • .*?<\\/li><\\/div>/gs) || [];\n if (divs.length > 0) {\n const items = divs.map(div => {\n // Extract indentation and list item\n const indentMatch = div.match(/
    ((?: )*)
  • .*?<\\/li>/);\n\n if (indentMatch && listItemMatch) {\n const indentation = indentMatch[1];\n const listItem = listItemMatch[0];\n // Insert indentation at the start of the list item content\n return listItem.replace(/
  • /, `
  • ${indentation}`);\n }\n return listItemMatch ? listItemMatch[0] : '';\n }).filter(Boolean);\n\n return '
      ' + items.join('') + '
    ';\n }\n return match;\n });\n\n // Process code blocks - KEEP the fence markers for alignment AND use semantic pre/code\n const codeBlockRegex = /
    (```[^<]*)<\\/span><\\/div>(.*?)
    (```)<\\/span><\\/div>/gs;\n processed = processed.replace(codeBlockRegex, (match, openFence, content, closeFence) => {\n // Extract the content between fences\n const lines = content.match(/
    (.*?)<\\/div>/gs) || [];\n const codeContent = lines.map(line => {\n // Extract text from each div - content is already escaped\n const text = line.replace(/
    (.*?)<\\/div>/s, '$1')\n .replace(/ /g, ' ');\n return text;\n }).join('\\n');\n\n // Extract language from the opening fence\n const lang = openFence.slice(3).trim();\n const langClass = lang ? ` class=\"language-${lang}\"` : '';\n\n // Apply code highlighting if available\n let highlightedContent = codeContent;\n // Use instance highlighter if provided, otherwise fall back to global highlighter\n const highlighter = instanceHighlighter || this.codeHighlighter;\n if (highlighter) {\n try {\n // CRITICAL: Decode HTML entities before passing to highlighter\n // In the DOM path, textContent automatically decodes entities.\n // In the manual path, we need to decode explicitly to avoid double-escaping.\n const decodedCode = codeContent\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&'); // Must be last to avoid double-decoding\n\n const result = highlighter(decodedCode, lang);\n\n // Check if result is a Promise (async highlighter)\n // Note: In Node.js context, we can't easily defer rendering, so we warn\n if (result && typeof result.then === 'function') {\n console.warn('Async highlighters are not supported in Node.js (non-DOM) context. Use synchronous highlighters for server-side rendering.');\n // Fall back to escaped content\n } else {\n // Synchronous highlighter - verify returned non-empty string\n if (result && typeof result === 'string' && result.trim()) {\n highlightedContent = result;\n }\n // else: keep the escaped codeContent as fallback\n }\n } catch (error) {\n console.warn('Code highlighting failed:', error);\n // Fall back to original content\n }\n }\n\n // Keep fence markers visible as separate divs, with pre/code block between them\n let result = `
    ${openFence}
    `;\n // Use highlighted content if available, otherwise use escaped content\n result += `
    ${highlightedContent}
    `;\n result += `
    ${closeFence}
    `;\n\n return result;\n });\n\n return processed;\n }\n\n /**\n * List pattern definitions\n */\n static LIST_PATTERNS = {\n bullet: /^(\\s*)([-*+])\\s+(.*)$/,\n numbered: /^(\\s*)(\\d+)\\.\\s+(.*)$/,\n checkbox: /^(\\s*)-\\s+\\[([ x])\\]\\s+(.*)$/\n };\n\n /**\n * Get list context at cursor position\n * @param {string} text - Full text content\n * @param {number} cursorPosition - Current cursor position\n * @returns {Object} List context information\n */\n static getListContext(text, cursorPosition) {\n // Find the line containing the cursor\n const lines = text.split('\\n');\n let currentPos = 0;\n let lineIndex = 0;\n let lineStart = 0;\n\n for (let i = 0; i < lines.length; i++) {\n const lineLength = lines[i].length;\n if (currentPos + lineLength >= cursorPosition) {\n lineIndex = i;\n lineStart = currentPos;\n break;\n }\n currentPos += lineLength + 1; // +1 for newline\n }\n\n const currentLine = lines[lineIndex];\n const lineEnd = lineStart + currentLine.length;\n\n // Check for checkbox first (most specific)\n const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);\n if (checkboxMatch) {\n return {\n inList: true,\n listType: 'checkbox',\n indent: checkboxMatch[1],\n marker: '-',\n checked: checkboxMatch[2] === 'x',\n content: checkboxMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5 // indent + \"- [ ] \"\n };\n }\n\n // Check for bullet list\n const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);\n if (bulletMatch) {\n return {\n inList: true,\n listType: 'bullet',\n indent: bulletMatch[1],\n marker: bulletMatch[2],\n content: bulletMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1 // indent + marker + space\n };\n }\n\n // Check for numbered list\n const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);\n if (numberedMatch) {\n return {\n inList: true,\n listType: 'numbered',\n indent: numberedMatch[1],\n marker: parseInt(numberedMatch[2]),\n content: numberedMatch[3],\n lineStart,\n lineEnd,\n markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2 // indent + number + \". \"\n };\n }\n\n // Not in a list\n return {\n inList: false,\n listType: null,\n indent: '',\n marker: null,\n content: currentLine,\n lineStart,\n lineEnd,\n markerEndPos: lineStart\n };\n }\n\n /**\n * Create a new list item based on context\n * @param {Object} context - List context from getListContext\n * @returns {string} New list item text\n */\n static createNewListItem(context) {\n switch (context.listType) {\n case 'bullet':\n return `${context.indent}${context.marker} `;\n case 'numbered':\n return `${context.indent}${context.marker + 1}. `;\n case 'checkbox':\n return `${context.indent}- [ ] `;\n default:\n return '';\n }\n }\n\n /**\n * Renumber all numbered lists in text\n * @param {string} text - Text containing numbered lists\n * @returns {string} Text with renumbered lists\n */\n static renumberLists(text) {\n const lines = text.split('\\n');\n const numbersByIndent = new Map();\n let inList = false;\n\n const result = lines.map(line => {\n const match = line.match(this.LIST_PATTERNS.numbered);\n\n if (match) {\n const indent = match[1];\n const indentLevel = indent.length;\n const content = match[3];\n\n // If we weren't in a list or indent changed, reset lower levels\n if (!inList) {\n numbersByIndent.clear();\n }\n\n // Get the next number for this indent level\n const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;\n numbersByIndent.set(indentLevel, currentNumber);\n\n // Clear deeper indent levels\n for (const [level] of numbersByIndent) {\n if (level > indentLevel) {\n numbersByIndent.delete(level);\n }\n }\n\n inList = true;\n return `${indent}${currentNumber}. ${content}`;\n } else {\n // Not a numbered list item\n if (line.trim() === '' || !line.match(/^\\s/)) {\n // Empty line or non-indented line breaks the list\n inList = false;\n numbersByIndent.clear();\n }\n return line;\n }\n });\n\n return result.join('\\n');\n }\n}\n", "/**\n * Keyboard shortcuts handler for OverType editor\n * Delegates to editor.performAction for consistent behavior\n */\n\n/**\n * ShortcutsManager - Handles keyboard shortcuts for the editor\n */\nexport class ShortcutsManager {\n constructor(editor) {\n this.editor = editor;\n }\n\n /**\n * Handle keydown events - called by OverType\n * @param {KeyboardEvent} event - The keyboard event\n * @returns {boolean} Whether the event was handled\n */\n handleKeydown(event) {\n const isMac = navigator.platform.toLowerCase().includes('mac');\n const modKey = isMac ? event.metaKey : event.ctrlKey;\n\n if (!modKey) return false;\n\n let actionId = null;\n\n switch (event.key.toLowerCase()) {\n case 'b':\n if (!event.shiftKey) actionId = 'toggleBold';\n break;\n case 'i':\n if (!event.shiftKey) actionId = 'toggleItalic';\n break;\n case 'k':\n if (!event.shiftKey) actionId = 'insertLink';\n break;\n case '7':\n if (event.shiftKey) actionId = 'toggleNumberedList';\n break;\n case '8':\n if (event.shiftKey) actionId = 'toggleBulletList';\n break;\n }\n\n if (actionId) {\n event.preventDefault();\n this.editor.performAction(actionId, event);\n return true;\n }\n\n return false;\n }\n\n /**\n * Cleanup\n */\n destroy() {\n // Nothing to clean up since we don't add our own listener\n }\n}\n", "/**\n * Built-in themes for OverType editor\n * Each theme provides a complete color palette for the editor\n */\n\n/**\n * Solar theme - Light, warm and bright\n */\nexport const solar = {\n name: 'solar',\n colors: {\n bgPrimary: '#faf0ca', // Lemon Chiffon - main background\n bgSecondary: '#ffffff', // White - editor background\n text: '#0d3b66', // Yale Blue - main text\n textPrimary: '#0d3b66', // Yale Blue - primary text (same as text)\n textSecondary: '#5a7a9b', // Muted blue - secondary text\n h1: '#f95738', // Tomato - h1 headers\n h2: '#ee964b', // Sandy Brown - h2 headers\n h3: '#3d8a51', // Forest green - h3 headers\n strong: '#ee964b', // Sandy Brown - bold text\n em: '#f95738', // Tomato - italic text\n del: '#ee964b', // Sandy Brown - deleted text (same as strong)\n link: '#0d3b66', // Yale Blue - links\n code: '#0d3b66', // Yale Blue - inline code\n codeBg: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n blockquote: '#5a7a9b', // Muted blue - blockquotes\n hr: '#5a7a9b', // Muted blue - horizontal rules\n syntaxMarker: 'rgba(13, 59, 102, 0.52)', // Yale Blue with transparency\n syntax: '#999999', // Gray - syntax highlighting fallback\n cursor: '#f95738', // Tomato - cursor\n selection: 'rgba(244, 211, 94, 0.4)', // Naples Yellow with transparency\n listMarker: '#ee964b', // Sandy Brown - list markers\n rawLine: '#5a7a9b', // Muted blue - raw line indicators\n border: '#e0e0e0', // Light gray - borders\n hoverBg: '#f0f0f0', // Very light gray - hover backgrounds\n primary: '#0d3b66', // Yale Blue - primary accent\n // Toolbar colors\n toolbarBg: '#ffffff', // White - toolbar background\n toolbarIcon: '#0d3b66', // Yale Blue - icon color\n toolbarHover: '#f5f5f5', // Light gray - hover background\n toolbarActive: '#faf0ca', // Lemon Chiffon - active button background\n }\n};\n\n/**\n * Cave theme - Dark ocean depths\n */\nexport const cave = {\n name: 'cave',\n colors: {\n bgPrimary: '#141E26', // Deep ocean - main background\n bgSecondary: '#1D2D3E', // Darker charcoal - editor background\n text: '#c5dde8', // Light blue-gray - main text\n textPrimary: '#c5dde8', // Light blue-gray - primary text (same as text)\n textSecondary: '#9fcfec', // Brighter blue - secondary text\n h1: '#d4a5ff', // Rich lavender - h1 headers\n h2: '#f6ae2d', // Hunyadi Yellow - h2 headers\n h3: '#9fcfec', // Brighter blue - h3 headers\n strong: '#f6ae2d', // Hunyadi Yellow - bold text\n em: '#9fcfec', // Brighter blue - italic text\n del: '#f6ae2d', // Hunyadi Yellow - deleted text (same as strong)\n link: '#9fcfec', // Brighter blue - links\n code: '#c5dde8', // Light blue-gray - inline code\n codeBg: '#1a232b', // Very dark blue - code background\n blockquote: '#9fcfec', // Brighter blue - same as italic\n hr: '#c5dde8', // Light blue-gray - horizontal rules\n syntaxMarker: 'rgba(159, 207, 236, 0.73)', // Brighter blue semi-transparent\n syntax: '#7a8c98', // Muted gray-blue - syntax highlighting fallback\n cursor: '#f26419', // Orange Pantone - cursor\n selection: 'rgba(51, 101, 138, 0.4)', // Lapis Lazuli with transparency\n listMarker: '#f6ae2d', // Hunyadi Yellow - list markers\n rawLine: '#9fcfec', // Brighter blue - raw line indicators\n border: '#2a3f52', // Dark blue-gray - borders\n hoverBg: '#243546', // Slightly lighter charcoal - hover backgrounds\n primary: '#9fcfec', // Brighter blue - primary accent\n // Toolbar colors for dark theme\n toolbarBg: '#1D2D3E', // Darker charcoal - toolbar background\n toolbarIcon: '#c5dde8', // Light blue-gray - icon color\n toolbarHover: '#243546', // Slightly lighter charcoal - hover background\n toolbarActive: '#2a3f52', // Even lighter - active button background\n }\n};\n\n/**\n * Auto theme - Automatically switches between solar and cave based on system preference\n * This is a special marker theme that triggers automatic theme switching\n */\nexport const auto = {\n name: 'auto',\n // The auto theme doesn't have its own colors; it uses solar or cave dynamically\n colors: solar.colors // Default to solar colors for initial render\n};\n\n/**\n * Default themes registry\n */\nexport const themes = {\n solar,\n cave,\n auto,\n // Aliases for backward compatibility\n light: solar,\n dark: cave\n};\n\n/**\n * Get theme by name or return custom theme object\n * @param {string|Object} theme - Theme name or custom theme object\n * @returns {Object} Theme configuration\n */\nexport function getTheme(theme) {\n if (typeof theme === 'string') {\n const themeObj = themes[theme] || themes.solar;\n // Preserve the requested theme name (important for 'light' and 'dark' aliases)\n return { ...themeObj, name: theme };\n }\n return theme;\n}\n\n// Cache media query for auto theme resolution\nlet _mq = null;\n\n/**\n * Resolve auto theme to actual theme based on system color scheme preference\n * @param {string} themeName - Theme name to resolve\n * @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise the original name)\n */\nexport function resolveAutoTheme(themeName) {\n if (themeName !== 'auto') return themeName;\n \n // Cache media query object\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n \n return _mq?.matches ? 'cave' : 'solar';\n}\n\n/**\n * Get the current system color scheme preference\n * @returns {string} 'dark' or 'light'\n */\nexport function getSystemColorScheme() {\n // Reuse cached media query if available\n if (!_mq && window.matchMedia) {\n _mq = window.matchMedia('(prefers-color-scheme: dark)');\n }\n return _mq?.matches ? 'dark' : 'light';\n}\n\n/**\n * Apply theme colors to CSS variables\n * @param {Object} colors - Theme colors object\n * @returns {string} CSS custom properties string\n */\nexport function themeToCSSVars(colors) {\n const vars = [];\n for (const [key, value] of Object.entries(colors)) {\n // Convert camelCase to kebab-case\n const varName = key.replace(/([A-Z])/g, '-$1').toLowerCase();\n vars.push(`--${varName}: ${value};`);\n }\n return vars.join('\\n');\n}\n\n/**\n * Merge custom colors with base theme\n * @param {Object} baseTheme - Base theme object\n * @param {Object} customColors - Custom color overrides\n * @returns {Object} Merged theme object\n */\nexport function mergeTheme(baseTheme, customColors = {}) {\n return {\n ...baseTheme,\n colors: {\n ...baseTheme.colors,\n ...customColors\n }\n };\n}", "/**\n * CSS styles for OverType editor\n * Embedded in JavaScript to ensure single-file distribution\n */\n\nimport { themeToCSSVars } from './themes.js';\n\n/**\n * Generate the complete CSS for the editor\n * @param {Object} options - Configuration options\n * @returns {string} Complete CSS string\n */\nexport function generateStyles(options = {}) {\n const {\n fontSize = '14px',\n lineHeight = 1.6,\n /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */\n fontFamily = '\"SF Mono\", SFMono-Regular, Menlo, Monaco, \"Cascadia Code\", Consolas, \"Roboto Mono\", \"Noto Sans Mono\", \"Droid Sans Mono\", \"Ubuntu Mono\", \"DejaVu Sans Mono\", \"Liberation Mono\", \"Courier New\", Courier, monospace',\n padding = '20px',\n theme = null,\n mobile = {}\n } = options;\n\n // Generate mobile overrides\n const mobileStyles = Object.keys(mobile).length > 0 ? `\n @media (max-width: 640px) {\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n ${Object.entries(mobile)\n .map(([prop, val]) => {\n const cssProp = prop.replace(/([A-Z])/g, '-$1').toLowerCase();\n return `${cssProp}: ${val} !important;`;\n })\n .join('\\n ')}\n }\n }\n ` : '';\n\n // Generate theme variables if provided\n const themeVars = theme && theme.colors ? themeToCSSVars(theme.colors) : '';\n\n return `\n /* OverType Editor Styles */\n \n /* Middle-ground CSS Reset - Prevent parent styles from leaking in */\n .overtype-container * {\n /* Box model - these commonly leak */\n margin: 0 !important;\n padding: 0 !important;\n border: 0 !important;\n \n /* Layout - these can break our layout */\n /* Don't reset position - it breaks dropdowns */\n float: none !important;\n clear: none !important;\n \n /* Typography - only reset decorative aspects */\n text-decoration: none !important;\n text-transform: none !important;\n letter-spacing: normal !important;\n \n /* Visual effects that can interfere */\n box-shadow: none !important;\n text-shadow: none !important;\n \n /* Ensure box-sizing is consistent */\n box-sizing: border-box !important;\n \n /* Keep inheritance for these */\n /* font-family, color, line-height, font-size - inherit */\n }\n \n /* Container base styles after reset */\n .overtype-container {\n display: flex !important;\n flex-direction: column !important;\n width: 100% !important;\n height: 100% !important;\n position: relative !important; /* Override reset - needed for absolute children */\n overflow: visible !important; /* Allow dropdown to overflow container */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n text-align: left !important;\n ${themeVars ? `\n /* Theme Variables */\n ${themeVars}` : ''}\n }\n \n /* Force left alignment for all elements in the editor */\n .overtype-container .overtype-wrapper * {\n text-align: left !important;\n }\n \n /* Auto-resize mode styles */\n .overtype-container.overtype-auto-resize {\n height: auto !important;\n }\n\n .overtype-container.overtype-auto-resize .overtype-wrapper {\n flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */\n height: auto !important;\n min-height: 60px !important;\n overflow: visible !important;\n }\n \n .overtype-wrapper {\n position: relative !important; /* Override reset - needed for absolute children */\n width: 100% !important;\n flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */\n min-height: 60px !important; /* Minimum usable height */\n overflow: hidden !important;\n background: var(--bg-secondary, #ffffff) !important;\n z-index: 1; /* Below toolbar and dropdown */\n }\n\n /* Critical alignment styles - must be identical for both layers */\n .overtype-wrapper .overtype-input,\n .overtype-wrapper .overtype-preview {\n /* Positioning - must be identical */\n position: absolute !important; /* Override reset - required for overlay */\n top: 0 !important;\n left: 0 !important;\n width: 100% !important;\n height: 100% !important;\n \n /* Font properties - any difference breaks alignment */\n font-family: ${fontFamily} !important;\n font-variant-ligatures: none !important; /* keep metrics stable for code */\n font-size: var(--instance-font-size, ${fontSize}) !important;\n line-height: var(--instance-line-height, ${lineHeight}) !important;\n font-weight: normal !important;\n font-style: normal !important;\n font-variant: normal !important;\n font-stretch: normal !important;\n font-kerning: none !important;\n font-feature-settings: normal !important;\n \n /* Box model - must match exactly */\n padding: var(--instance-padding, ${padding}) !important;\n margin: 0 !important;\n border: none !important;\n outline: none !important;\n box-sizing: border-box !important;\n \n /* Text layout - critical for character positioning */\n white-space: pre-wrap !important;\n word-wrap: break-word !important;\n word-break: normal !important;\n overflow-wrap: break-word !important;\n tab-size: 2 !important;\n -moz-tab-size: 2 !important;\n text-align: left !important;\n text-indent: 0 !important;\n letter-spacing: normal !important;\n word-spacing: normal !important;\n \n /* Text rendering */\n text-transform: none !important;\n text-rendering: auto !important;\n -webkit-font-smoothing: auto !important;\n -webkit-text-size-adjust: 100% !important;\n \n /* Direction and writing */\n direction: ltr !important;\n writing-mode: horizontal-tb !important;\n unicode-bidi: normal !important;\n text-orientation: mixed !important;\n \n /* Visual effects that could shift perception */\n text-shadow: none !important;\n filter: none !important;\n transform: none !important;\n zoom: 1 !important;\n \n /* Vertical alignment */\n vertical-align: baseline !important;\n \n /* Size constraints */\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n \n /* Overflow */\n overflow-y: auto !important;\n overflow-x: auto !important;\n /* overscroll-behavior removed to allow scroll-through to parent */\n scrollbar-width: auto !important;\n scrollbar-gutter: auto !important;\n \n /* Animation/transition - disabled to prevent movement */\n animation: none !important;\n transition: none !important;\n }\n\n /* Input layer styles */\n .overtype-wrapper .overtype-input {\n /* Layer positioning */\n z-index: 1 !important;\n \n /* Text visibility */\n color: transparent !important;\n caret-color: var(--cursor, #f95738) !important;\n background-color: transparent !important;\n \n /* Textarea-specific */\n resize: none !important;\n appearance: none !important;\n -webkit-appearance: none !important;\n -moz-appearance: none !important;\n \n /* Prevent mobile zoom on focus */\n touch-action: manipulation !important;\n \n /* Disable autofill and spellcheck */\n autocomplete: off !important;\n autocorrect: off !important;\n autocapitalize: off !important;\n spellcheck: false !important;\n }\n\n .overtype-wrapper .overtype-input::selection {\n background-color: var(--selection, rgba(244, 211, 94, 0.4));\n }\n\n /* Preview layer styles */\n .overtype-wrapper .overtype-preview {\n /* Layer positioning */\n z-index: 0 !important;\n pointer-events: none !important;\n color: var(--text, #0d3b66) !important;\n background-color: transparent !important;\n \n /* Prevent text selection */\n user-select: none !important;\n -webkit-user-select: none !important;\n -moz-user-select: none !important;\n -ms-user-select: none !important;\n }\n\n /* Defensive styles for preview child divs */\n .overtype-wrapper .overtype-preview div {\n /* Reset any inherited styles */\n margin: 0 !important;\n padding: 0 !important;\n border: none !important;\n text-align: left !important;\n text-indent: 0 !important;\n display: block !important;\n position: static !important;\n transform: none !important;\n min-height: 0 !important;\n max-height: none !important;\n line-height: inherit !important;\n font-size: inherit !important;\n font-family: inherit !important;\n }\n\n /* Markdown element styling - NO SIZE CHANGES */\n .overtype-wrapper .overtype-preview .header {\n font-weight: bold !important;\n }\n\n /* Header colors */\n .overtype-wrapper .overtype-preview .h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview .h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview .h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Semantic headers - flatten in edit mode */\n .overtype-wrapper .overtype-preview h1,\n .overtype-wrapper .overtype-preview h2,\n .overtype-wrapper .overtype-preview h3 {\n font-size: inherit !important;\n font-weight: bold !important;\n margin: 0 !important;\n padding: 0 !important;\n display: inline !important;\n line-height: inherit !important;\n }\n\n /* Header colors for semantic headers */\n .overtype-wrapper .overtype-preview h1 { \n color: var(--h1, #f95738) !important; \n }\n .overtype-wrapper .overtype-preview h2 { \n color: var(--h2, #ee964b) !important; \n }\n .overtype-wrapper .overtype-preview h3 { \n color: var(--h3, #3d8a51) !important; \n }\n\n /* Lists - remove styling in edit mode */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n display: block !important; /* Lists need to be block for line breaks */\n }\n\n .overtype-wrapper .overtype-preview li {\n display: block !important; /* Each item on its own line */\n margin: 0 !important;\n padding: 0 !important;\n /* Don't set list-style here - let ul/ol control it */\n }\n\n /* Bold text */\n .overtype-wrapper .overtype-preview strong {\n color: var(--strong, #ee964b) !important;\n font-weight: bold !important;\n }\n\n /* Italic text */\n .overtype-wrapper .overtype-preview em {\n color: var(--em, #f95738) !important;\n text-decoration-color: var(--em, #f95738) !important;\n text-decoration-thickness: 1px !important;\n font-style: italic !important;\n }\n\n /* Strikethrough text */\n .overtype-wrapper .overtype-preview del {\n color: var(--del, #ee964b) !important;\n text-decoration: line-through !important;\n text-decoration-color: var(--del, #ee964b) !important;\n text-decoration-thickness: 1px !important;\n }\n\n /* Inline code */\n .overtype-wrapper .overtype-preview code {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n color: var(--code, #0d3b66) !important;\n padding: 0 !important;\n border-radius: 2px !important;\n font-family: inherit !important;\n font-size: inherit !important;\n line-height: inherit !important;\n font-weight: normal !important;\n }\n\n /* Code blocks - consolidated pre blocks */\n .overtype-wrapper .overtype-preview pre {\n padding: 0 !important;\n margin: 0 !important;\n border-radius: 4px !important;\n overflow-x: auto !important;\n }\n \n /* Code block styling in normal mode - yellow background */\n .overtype-wrapper .overtype-preview pre.code-block {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */\n }\n\n /* Code inside pre blocks - remove background */\n .overtype-wrapper .overtype-preview pre code {\n background: transparent !important;\n color: var(--code, #0d3b66) !important;\n font-family: ${fontFamily} !important; /* Match textarea font exactly for alignment */\n }\n\n /* Blockquotes */\n .overtype-wrapper .overtype-preview .blockquote {\n color: var(--blockquote, #5a7a9b) !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n }\n\n /* Links */\n .overtype-wrapper .overtype-preview a {\n color: var(--link, #0d3b66) !important;\n text-decoration: underline !important;\n font-weight: normal !important;\n }\n\n .overtype-wrapper .overtype-preview a:hover {\n text-decoration: underline !important;\n color: var(--link, #0d3b66) !important;\n }\n\n /* Lists - no list styling */\n .overtype-wrapper .overtype-preview ul,\n .overtype-wrapper .overtype-preview ol {\n list-style: none !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n\n /* Horizontal rules */\n .overtype-wrapper .overtype-preview hr {\n border: none !important;\n color: var(--hr, #5a7a9b) !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n .overtype-wrapper .overtype-preview .hr-marker {\n color: var(--hr, #5a7a9b) !important;\n opacity: 0.6 !important;\n }\n\n /* Code fence markers - with background when not in code block */\n .overtype-wrapper .overtype-preview .code-fence {\n color: var(--code, #0d3b66) !important;\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Code block lines - background for entire code block */\n .overtype-wrapper .overtype-preview .code-block-line {\n background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;\n }\n \n /* Remove background from code fence when inside code block line */\n .overtype-wrapper .overtype-preview .code-block-line .code-fence {\n background: transparent !important;\n }\n\n /* Raw markdown line */\n .overtype-wrapper .overtype-preview .raw-line {\n color: var(--raw-line, #5a7a9b) !important;\n font-style: normal !important;\n font-weight: normal !important;\n }\n\n /* Syntax markers */\n .overtype-wrapper .overtype-preview .syntax-marker {\n color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important;\n opacity: 0.7 !important;\n }\n\n /* List markers */\n .overtype-wrapper .overtype-preview .list-marker {\n color: var(--list-marker, #ee964b) !important;\n }\n\n /* Stats bar */\n \n /* Stats bar - positioned by flexbox */\n .overtype-stats {\n height: 40px !important;\n padding: 0 20px !important;\n background: #f8f9fa !important;\n border-top: 1px solid #e0e0e0 !important;\n display: flex !important;\n justify-content: space-between !important;\n align-items: center !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;\n font-size: 0.85rem !important;\n color: #666 !important;\n flex-shrink: 0 !important; /* Don't shrink */\n z-index: 10001 !important; /* Above link tooltip */\n position: relative !important; /* Enable z-index */\n }\n \n /* Dark theme stats bar */\n .overtype-container[data-theme=\"cave\"] .overtype-stats {\n background: var(--bg-secondary, #1D2D3E) !important;\n border-top: 1px solid rgba(197, 221, 232, 0.1) !important;\n color: var(--text, #c5dde8) !important;\n }\n \n .overtype-stats .overtype-stat {\n display: flex !important;\n align-items: center !important;\n gap: 5px !important;\n white-space: nowrap !important;\n }\n \n .overtype-stats .live-dot {\n width: 8px !important;\n height: 8px !important;\n background: #4caf50 !important;\n border-radius: 50% !important;\n animation: overtype-pulse 2s infinite !important;\n }\n \n @keyframes overtype-pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.6; transform: scale(1.2); }\n }\n \n\n /* Toolbar Styles */\n .overtype-toolbar {\n display: flex !important;\n align-items: center !important;\n gap: 4px !important;\n padding: 8px !important; /* Override reset */\n background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */\n border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */\n overflow-x: auto !important; /* Allow horizontal scrolling */\n overflow-y: hidden !important; /* Hide vertical overflow */\n -webkit-overflow-scrolling: touch !important;\n flex-shrink: 0 !important;\n height: auto !important;\n position: relative !important; /* Override reset */\n z-index: 100 !important; /* Ensure toolbar is above wrapper */\n scrollbar-width: thin; /* Thin scrollbar on Firefox */\n }\n \n /* Thin scrollbar styling */\n .overtype-toolbar::-webkit-scrollbar {\n height: 4px;\n }\n \n .overtype-toolbar::-webkit-scrollbar-track {\n background: transparent;\n }\n \n .overtype-toolbar::-webkit-scrollbar-thumb {\n background: rgba(0, 0, 0, 0.2);\n border-radius: 2px;\n }\n\n .overtype-toolbar-button {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n border: none;\n border-radius: 6px;\n background: transparent;\n color: var(--toolbar-icon, var(--text-secondary, #666));\n cursor: pointer;\n transition: all 0.2s ease;\n flex-shrink: 0;\n }\n\n .overtype-toolbar-button svg {\n width: 20px;\n height: 20px;\n fill: currentColor;\n }\n\n .overtype-toolbar-button:hover {\n background: var(--toolbar-hover, var(--bg-secondary, #e9ecef));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:active {\n transform: scale(0.95);\n }\n\n .overtype-toolbar-button.active {\n background: var(--toolbar-active, var(--primary, #007bff));\n color: var(--toolbar-icon, var(--text-primary, #333));\n }\n\n .overtype-toolbar-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .overtype-toolbar-separator {\n width: 1px;\n height: 24px;\n background: var(--border, #e0e0e0);\n margin: 0 4px;\n flex-shrink: 0;\n }\n\n /* Adjust wrapper when toolbar is present */\n /* Mobile toolbar adjustments */\n @media (max-width: 640px) {\n .overtype-toolbar {\n padding: 6px;\n gap: 2px;\n }\n\n .overtype-toolbar-button {\n width: 36px;\n height: 36px;\n }\n\n .overtype-toolbar-separator {\n margin: 0 2px;\n }\n }\n \n /* Plain mode - hide preview and show textarea text */\n .overtype-container[data-mode=\"plain\"] .overtype-preview {\n display: none !important;\n }\n \n .overtype-container[data-mode=\"plain\"] .overtype-input {\n color: var(--text, #0d3b66) !important;\n /* Use system font stack for better plain text readability */\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \n \"Helvetica Neue\", Arial, sans-serif !important;\n }\n \n /* Ensure textarea remains transparent in overlay mode */\n .overtype-container:not([data-mode=\"plain\"]) .overtype-input {\n color: transparent !important;\n }\n\n /* Dropdown menu styles */\n .overtype-toolbar-button {\n position: relative !important; /* Override reset - needed for dropdown */\n }\n\n .overtype-toolbar-button.dropdown-active {\n background: var(--toolbar-active, var(--hover-bg, #f0f0f0));\n }\n\n .overtype-dropdown-menu {\n position: fixed !important; /* Fixed positioning relative to viewport */\n background: var(--bg-secondary, white) !important; /* Override reset */\n border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */\n border-radius: 6px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */\n z-index: 10000; /* Very high z-index to ensure visibility */\n min-width: 150px;\n padding: 4px 0 !important; /* Override reset */\n /* Position will be set via JavaScript based on button position */\n }\n\n .overtype-dropdown-item {\n display: flex;\n align-items: center;\n width: 100%;\n padding: 8px 12px;\n border: none;\n background: none;\n text-align: left;\n cursor: pointer;\n font-size: 14px;\n color: var(--text, #333);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n }\n\n .overtype-dropdown-item:hover {\n background: var(--hover-bg, #f0f0f0);\n }\n\n .overtype-dropdown-item.active {\n font-weight: 600;\n }\n\n .overtype-dropdown-check {\n width: 16px;\n margin-right: 8px;\n color: var(--h1, #007bff);\n }\n\n .overtype-dropdown-icon {\n width: 20px;\n margin-right: 8px;\n text-align: center;\n }\n\n /* Preview mode styles */\n .overtype-container[data-mode=\"preview\"] .overtype-input {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-preview {\n pointer-events: auto !important;\n user-select: text !important;\n cursor: text !important;\n }\n\n /* Hide syntax markers in preview mode */\n .overtype-container[data-mode=\"preview\"] .syntax-marker {\n display: none !important;\n }\n \n /* Hide URL part of links in preview mode - extra specificity */\n .overtype-container[data-mode=\"preview\"] .syntax-marker.url-part,\n .overtype-container[data-mode=\"preview\"] .url-part {\n display: none !important;\n }\n \n /* Hide all syntax markers inside links too */\n .overtype-container[data-mode=\"preview\"] a .syntax-marker {\n display: none !important;\n }\n\n /* Headers - restore proper sizing in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2, \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif !important;\n font-weight: 600 !important;\n margin: 0 !important;\n display: block !important;\n color: inherit !important; /* Use parent text color */\n line-height: 1 !important; /* Tight line height for headings */\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h1 { \n font-size: 2em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h2 { \n font-size: 1.5em !important; \n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview h3 { \n font-size: 1.17em !important; \n }\n\n /* Lists - restore list styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ul {\n display: block !important;\n list-style: disc !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview ol {\n display: block !important;\n list-style: decimal !important;\n padding-left: 2em !important;\n margin: 1em 0 !important;\n }\n \n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li {\n display: list-item !important;\n margin: 0 !important;\n padding: 0 !important;\n }\n\n /* Task list checkboxes - only in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n position: relative !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview li.task-list input[type=\"checkbox\"] {\n margin-right: 0.5em !important;\n cursor: default !important;\n vertical-align: middle !important;\n }\n\n /* Task list in normal mode - keep syntax visible */\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list {\n list-style: none !important;\n }\n\n .overtype-container:not([data-mode=\"preview\"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker {\n color: var(--syntax, #999999) !important;\n font-weight: normal !important;\n }\n\n /* Links - make clickable in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview a {\n pointer-events: auto !important;\n cursor: pointer !important;\n color: var(--link, #0066cc) !important;\n text-decoration: underline !important;\n }\n\n /* Code blocks - proper pre/code styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #2d2d2d !important;\n color: #f8f8f2 !important;\n padding: 1.2em !important;\n border-radius: 3px !important;\n overflow-x: auto !important;\n margin: 0 !important;\n display: block !important;\n }\n \n /* Cave theme code block background in preview mode */\n .overtype-container[data-theme=\"cave\"][data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block {\n background: #11171F !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview pre.code-block code {\n background: transparent !important;\n color: inherit !important;\n padding: 0 !important;\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n line-height: 1.4 !important;\n }\n\n /* Hide old code block lines and fences in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-block-line {\n display: none !important;\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .code-fence {\n display: none !important;\n }\n\n /* Blockquotes - enhanced styling in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .blockquote {\n display: block !important;\n border-left: 4px solid var(--blockquote, #ddd) !important;\n padding-left: 1em !important;\n margin: 1em 0 !important;\n font-style: italic !important;\n }\n\n /* Typography improvements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview {\n font-family: Georgia, 'Times New Roman', serif !important;\n font-size: 16px !important;\n line-height: 1.8 !important;\n color: var(--text, #333) !important; /* Consistent text color */\n }\n\n /* Inline code in preview mode - keep monospace */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview code {\n font-family: ${fontFamily} !important;\n font-size: 0.9em !important;\n background: rgba(135, 131, 120, 0.15) !important;\n padding: 0.2em 0.4em !important;\n border-radius: 3px !important;\n }\n\n /* Strong and em elements in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview strong {\n font-weight: 700 !important;\n color: inherit !important; /* Use parent text color */\n }\n\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview em {\n font-style: italic !important;\n color: inherit !important; /* Use parent text color */\n }\n\n /* HR in preview mode */\n .overtype-container[data-mode=\"preview\"] .overtype-wrapper .overtype-preview .hr-marker {\n display: block !important;\n border-top: 2px solid var(--hr, #ddd) !important;\n text-indent: -9999px !important;\n height: 2px !important;\n }\n\n /* Link Tooltip - Base styles (all browsers) */\n .overtype-link-tooltip {\n /* Visual styles that work for both positioning methods */\n background: #333 !important;\n color: white !important;\n padding: 6px 10px !important;\n border-radius: 16px !important;\n font-size: 12px !important;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;\n display: none !important;\n z-index: 10000 !important;\n cursor: pointer !important;\n box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;\n max-width: 300px !important;\n white-space: nowrap !important;\n overflow: hidden !important;\n text-overflow: ellipsis !important;\n\n /* Base positioning for Floating UI fallback */\n position: absolute;\n }\n\n .overtype-link-tooltip.visible {\n display: flex !important;\n }\n\n /* CSS Anchor Positioning (modern browsers only) */\n @supports (position-anchor: --x) and (position-area: center) {\n .overtype-link-tooltip {\n /* Only anchor positioning specific properties */\n position-anchor: var(--target-anchor, --link-0);\n position-area: block-end center;\n margin-top: 8px !important;\n position-try: most-width block-end inline-end, flip-inline, block-start center;\n position-visibility: anchors-visible;\n }\n }\n\n ${mobileStyles}\n `;\n}", "/**\n * Format definitions for markdown syntax\n */\n\nexport const FORMATS = {\n bold: {\n prefix: '**',\n suffix: '**',\n trimFirst: true\n },\n italic: {\n prefix: '_',\n suffix: '_',\n trimFirst: true\n },\n code: {\n prefix: '`',\n suffix: '`',\n blockPrefix: '```',\n blockSuffix: '```'\n },\n link: {\n prefix: '[',\n suffix: '](url)',\n replaceNext: 'url',\n scanFor: 'https?://'\n },\n bulletList: {\n prefix: '- ',\n multiline: true,\n unorderedList: true\n },\n numberedList: {\n prefix: '1. ',\n multiline: true,\n orderedList: true\n },\n quote: {\n prefix: '> ',\n multiline: true,\n surroundWithNewlines: true\n },\n taskList: {\n prefix: '- [ ] ',\n multiline: true,\n surroundWithNewlines: true\n },\n header1: { prefix: '# ' },\n header2: { prefix: '## ' },\n header3: { prefix: '### ' },\n header4: { prefix: '#### ' },\n header5: { prefix: '##### ' },\n header6: { prefix: '###### ' }\n}\n\n/**\n * Default style configuration\n */\nexport function getDefaultStyle() {\n return {\n prefix: '',\n suffix: '',\n blockPrefix: '',\n blockSuffix: '',\n multiline: false,\n replaceNext: '',\n prefixSpace: false,\n scanFor: '',\n surroundWithNewlines: false,\n orderedList: false,\n unorderedList: false,\n trimFirst: false\n }\n}\n\n/**\n * Merge format with defaults\n */\nexport function mergeWithDefaults(format) {\n return { ...getDefaultStyle(), ...format }\n}", "/**\n * Debug utilities for markdown-actions\n * Add console logging to track what's happening\n */\n\n// Debug mode flag - disabled by default\nlet debugMode = false;\n\n/**\n * Enable or disable debug mode\n * @param {boolean} enabled - Whether to enable debug mode\n */\nexport function setDebugMode(enabled) {\n debugMode = enabled;\n}\n\n/**\n * Get current debug mode status\n * @returns {boolean} Whether debug mode is enabled\n */\nexport function getDebugMode() {\n return debugMode;\n}\n\nexport function debugLog(funcName, message, data) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group(`\uD83D\uDD0D ${funcName}`);\n console.log(message);\n if (data) {\n console.log('Data:', data);\n }\n console.groupEnd();\n}\n\nexport function debugSelection(textarea, label) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);\n console.group(`\uD83D\uDCCD Selection: ${label}`);\n console.log('Position:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Selected text:', JSON.stringify(selected));\n console.log('Length:', selected.length);\n \n // Show context around selection\n const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);\n const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));\n console.log('Context:', JSON.stringify(before) + '[SELECTION]' + JSON.stringify(after));\n console.groupEnd();\n}\n\nexport function debugResult(result) {\n // These will be completely removed by esbuild's drop: ['console'] in production\n if (!debugMode) return;\n \n console.group('\uD83D\uDCDD Result');\n console.log('Text to insert:', JSON.stringify(result.text));\n console.log('New selection:', `${result.selectionStart}-${result.selectionEnd}`);\n console.groupEnd();\n}", "/**\n * Text insertion system with undo/redo support\n * Extracted and adapted from GitHub's markdown-toolbar-element\n */\n\nimport { getDebugMode } from '../debug.js'\n\nlet canInsertText = null\n\n/**\n * Insert text at current position with undo/redo support\n * @param {HTMLTextAreaElement} textarea - Target textarea\n * @param {Object} options - Text and selection options\n * @param {string} options.text - Text to insert\n * @param {number} [options.selectionStart] - New selection start\n * @param {number} [options.selectionEnd] - New selection end\n */\nexport function insertText(textarea, { text, selectionStart, selectionEnd }) {\n const debugMode = getDebugMode();\n \n if (debugMode) {\n console.group('\uD83D\uDD27 insertText');\n console.log('Current selection:', `${textarea.selectionStart}-${textarea.selectionEnd}`);\n console.log('Text to insert:', JSON.stringify(text));\n console.log('New selection to set:', selectionStart, '-', selectionEnd);\n }\n \n // Make sure the textarea is focused\n textarea.focus();\n \n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n const before = textarea.value.slice(0, originalSelectionStart)\n const after = textarea.value.slice(originalSelectionEnd)\n \n if (debugMode) {\n console.log('Before text (last 20):', JSON.stringify(before.slice(-20)));\n console.log('After text (first 20):', JSON.stringify(after.slice(0, 20)));\n console.log('Selected text being replaced:', JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));\n }\n \n // Store the original value to check if execCommand actually changed it\n const originalValue = textarea.value\n\n // Try execCommand for both insertions and replacements to preserve undo history\n // execCommand('insertText') can handle replacing selected text\n const hasSelection = originalSelectionStart !== originalSelectionEnd\n \n if (canInsertText === null || canInsertText === true) {\n textarea.contentEditable = 'true'\n try {\n canInsertText = document.execCommand('insertText', false, text)\n if (debugMode) console.log('execCommand returned:', canInsertText, 'for text with', text.split('\\n').length, 'lines');\n } catch (error) {\n canInsertText = false\n if (debugMode) console.log('execCommand threw error:', error);\n }\n textarea.contentEditable = 'false'\n }\n\n if (debugMode) {\n console.log('canInsertText before:', canInsertText);\n console.log('execCommand result:', canInsertText);\n }\n \n // Check if execCommand actually worked by comparing the value\n if (canInsertText) {\n const expectedValue = before + text + after\n const actualValue = textarea.value\n \n if (debugMode) {\n console.log('Expected length:', expectedValue.length);\n console.log('Actual length:', actualValue.length);\n }\n \n if (actualValue !== expectedValue) {\n if (debugMode) {\n console.log('execCommand changed the value but not as expected');\n console.log('Expected:', JSON.stringify(expectedValue.slice(0, 100)));\n console.log('Actual:', JSON.stringify(actualValue.slice(0, 100)));\n }\n // Don't set canInsertText to false here - execCommand did work\n // We just need to not double-insert\n }\n }\n\n if (!canInsertText) {\n if (debugMode) console.log('Using manual insertion');\n // Only do manual insertion if execCommand didn't change the value\n if (textarea.value === originalValue) {\n if (debugMode) console.log('Value unchanged, doing manual replacement');\n try {\n document.execCommand('ms-beginUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.value = before + text + after\n try {\n document.execCommand('ms-endUndoUnit')\n } catch (e) {\n // Do nothing.\n }\n textarea.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }))\n } else {\n if (debugMode) console.log('Value was changed by execCommand, skipping manual insertion');\n }\n }\n\n if (debugMode) console.log('Setting selection range:', selectionStart, selectionEnd);\n if (selectionStart != null && selectionEnd != null) {\n textarea.setSelectionRange(selectionStart, selectionEnd)\n } else {\n textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd)\n }\n \n if (debugMode) {\n console.log('Final value length:', textarea.value.length);\n console.groupEnd();\n }\n}\n\n/**\n * Configure undo method\n * @param {'native' | 'manual' | 'auto'} method - Undo method to use\n */\nexport function setUndoMethod(method) {\n switch (method) {\n case 'native':\n canInsertText = true\n break\n case 'manual':\n canInsertText = false\n break\n case 'auto':\n canInsertText = null\n break\n }\n}", "/**\n * Core selection utilities extracted and adapted from GitHub's markdown-toolbar-element\n */\n\n/**\n * Check if string contains multiple lines\n */\nexport function isMultipleLines(string) {\n return string.trim().split('\\n').length > 1\n}\n\n/**\n * Find the start of the word at position i\n */\nexport function wordSelectionStart(text, i) {\n let index = i\n while (text[index] && text[index - 1] != null && !text[index - 1].match(/\\s/)) {\n index--\n }\n return index\n}\n\n/**\n * Find the end of the word at position i\n */\nexport function wordSelectionEnd(text, i, multiline) {\n let index = i\n const breakpoint = multiline ? /\\n/ : /\\s/\n while (text[index] && !text[index].match(breakpoint)) {\n index++\n }\n return index\n}\n\n/**\n * Expand selection to line boundaries\n */\nexport function expandSelectionToLine(textarea) {\n const lines = textarea.value.split('\\n')\n let counter = 0\n for (let index = 0; index < lines.length; index++) {\n const lineLength = lines[index].length + 1\n if (textarea.selectionStart >= counter && textarea.selectionStart < counter + lineLength) {\n textarea.selectionStart = counter\n }\n if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {\n // For the last line, don't go past the actual text length\n if (index === lines.length - 1) {\n textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length)\n } else {\n textarea.selectionEnd = counter + lineLength - 1\n }\n }\n counter += lineLength\n }\n}\n\n/**\n * Expand selected text with smart boundary detection\n */\nexport function expandSelectedText(textarea, prefixToUse, suffixToUse, multiline = false) {\n if (textarea.selectionStart === textarea.selectionEnd) {\n textarea.selectionStart = wordSelectionStart(textarea.value, textarea.selectionStart)\n textarea.selectionEnd = wordSelectionEnd(textarea.value, textarea.selectionEnd, multiline)\n } else {\n const expandedSelectionStart = textarea.selectionStart - prefixToUse.length\n const expandedSelectionEnd = textarea.selectionEnd + suffixToUse.length\n const beginsWithPrefix = textarea.value.slice(expandedSelectionStart, textarea.selectionStart) === prefixToUse\n const endsWithSuffix = textarea.value.slice(textarea.selectionEnd, expandedSelectionEnd) === suffixToUse\n if (beginsWithPrefix && endsWithSuffix) {\n textarea.selectionStart = expandedSelectionStart\n textarea.selectionEnd = expandedSelectionEnd\n }\n }\n return textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n}\n\n/**\n * Calculate newlines needed to surround selected text\n */\nexport function newlinesToSurroundSelectedText(textarea) {\n const beforeSelection = textarea.value.slice(0, textarea.selectionStart)\n const afterSelection = textarea.value.slice(textarea.selectionEnd)\n\n const breaksBefore = beforeSelection.match(/\\n*$/)\n const breaksAfter = afterSelection.match(/^\\n*/)\n const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0\n const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0\n\n let newlinesToAppend = ''\n let newlinesToPrepend = ''\n\n if (beforeSelection.match(/\\S/) && newlinesBeforeSelection < 2) {\n newlinesToAppend = '\\n'.repeat(2 - newlinesBeforeSelection)\n }\n\n if (afterSelection.match(/\\S/) && newlinesAfterSelection < 2) {\n newlinesToPrepend = '\\n'.repeat(2 - newlinesAfterSelection)\n }\n\n return { newlinesToAppend, newlinesToPrepend }\n}\n\n/**\n * Utility to preserve selection during operations\n */\nexport function preserveSelection(textarea, callback) {\n const start = textarea.selectionStart\n const end = textarea.selectionEnd\n const scrollTop = textarea.scrollTop\n \n callback()\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n textarea.scrollTop = scrollTop\n}\n\n/**\n * Apply a line-based operation with cursor preservation\n * This function handles expanding to line boundaries and preserving cursor position\n * @param {HTMLTextAreaElement} textarea - The textarea element\n * @param {Function} operation - The operation to perform (receives textarea and returns result)\n * @param {Object} options - Options for the operation\n * @param {string} options.prefix - The prefix being added/removed (for cursor adjustment)\n * @param {Function} options.adjustSelection - Custom selection adjustment function\n * @returns {Object} The result from the operation with adjusted cursor position\n */\nexport function applyLineOperation(textarea, operation, options = {}) {\n // Save original cursor position AND selection before any expansion\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n const noInitialSelection = originalStart === originalEnd\n \n // Store the line start position to calculate offset later\n const value = textarea.value\n let lineStart = originalStart\n \n // Find start of the line containing the selection start\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n \n // Expand selection to line boundaries for the operation\n if (noInitialSelection) {\n // Expand to current line when no selection\n let lineEnd = originalStart\n \n // Find end of current line\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else {\n // For selections, expand to full lines\n expandSelectionToLine(textarea)\n }\n \n // Apply the operation\n const result = operation(textarea)\n \n // Restore original selection/cursor with prefix adjustment\n if (options.adjustSelection) {\n // Use custom selection adjustment logic\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n const adjusted = options.adjustSelection(isRemoving, originalStart, originalEnd, lineStart)\n result.selectionStart = adjusted.start\n result.selectionEnd = adjusted.end\n } else if (options.prefix) {\n // Use default prefix-based adjustment\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n const isRemoving = selectedText.startsWith(options.prefix)\n \n if (noInitialSelection) {\n // No selection - just restore cursor position\n if (isRemoving) {\n // When removing prefix, adjust cursor position\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = result.selectionStart\n } else {\n // When adding prefix, adjust cursor position\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = result.selectionStart\n }\n } else {\n // Had a selection - restore it with adjustment\n if (isRemoving) {\n // When removing prefix, shift selection back\n result.selectionStart = Math.max(originalStart - options.prefix.length, lineStart)\n result.selectionEnd = Math.max(originalEnd - options.prefix.length, lineStart)\n } else {\n // When adding prefix, shift selection forward\n result.selectionStart = originalStart + options.prefix.length\n result.selectionEnd = originalEnd + options.prefix.length\n }\n }\n }\n \n return result\n}", "/**\n * Block-level text formatting operations\n * Handles inline formats like bold, italic, code, and links\n */\n\nimport { expandSelectedText, newlinesToSurroundSelectedText, isMultipleLines } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Apply block-level styling to selected text\n */\nexport function blockStyle(textarea, style) {\n let newlinesToAppend\n let newlinesToPrepend\n\n const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style\n const originalSelectionStart = textarea.selectionStart\n const originalSelectionEnd = textarea.selectionEnd\n\n let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}\\n` : prefix\n let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `\\n${blockSuffix}` : suffix\n\n if (prefixSpace) {\n const beforeSelection = textarea.value[textarea.selectionStart - 1]\n if (textarea.selectionStart !== 0 && beforeSelection != null && !beforeSelection.match(/\\s/)) {\n prefixToUse = ` ${prefixToUse}`\n }\n }\n \n selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0\n \n if (surroundWithNewlines) {\n const ref = newlinesToSurroundSelectedText(textarea)\n newlinesToAppend = ref.newlinesToAppend\n newlinesToPrepend = ref.newlinesToPrepend\n prefixToUse = newlinesToAppend + prefix\n suffixToUse += newlinesToPrepend\n }\n\n // Check if we should remove formatting (toggle off)\n if (selectedText.startsWith(prefixToUse) && selectedText.endsWith(suffixToUse)) {\n const replacementText = selectedText.slice(prefixToUse.length, selectedText.length - suffixToUse.length)\n if (originalSelectionStart === originalSelectionEnd) {\n let position = originalSelectionStart - prefixToUse.length\n position = Math.max(position, selectionStart)\n position = Math.min(position, selectionStart + replacementText.length)\n selectionStart = selectionEnd = position\n } else {\n selectionEnd = selectionStart + replacementText.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (!hasReplaceNext) {\n // Add formatting\n let replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = originalSelectionStart + prefixToUse.length\n selectionEnd = originalSelectionEnd + prefixToUse.length\n const whitespaceEdges = selectedText.match(/^\\s*|\\s*$/g)\n if (trimFirst && whitespaceEdges) {\n const leadingWhitespace = whitespaceEdges[0] || ''\n const trailingWhitespace = whitespaceEdges[1] || ''\n replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace\n selectionStart += leadingWhitespace.length\n selectionEnd -= trailingWhitespace.length\n }\n return { text: replacementText, selectionStart, selectionEnd }\n } else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {\n // Handle link/image with URL detection\n suffixToUse = suffixToUse.replace(replaceNext, selectedText)\n const replacementText = prefixToUse + suffixToUse\n selectionStart = selectionEnd = selectionStart + prefixToUse.length\n return { text: replacementText, selectionStart, selectionEnd }\n } else {\n // Handle link/image with placeholder\n const replacementText = prefixToUse + selectedText + suffixToUse\n selectionStart = selectionStart + prefixToUse.length + selectedText.length + suffixToUse.indexOf(replaceNext)\n selectionEnd = selectionStart + replaceNext.length\n return { text: replacementText, selectionStart, selectionEnd }\n }\n}\n\n/**\n * Apply style to selected text in textarea\n */\nexport function styleSelectedText(textarea, style) {\n const text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n \n let result\n if (style.orderedList || style.unorderedList) {\n // Will be handled by list operations\n return\n } else if (style.multiline && isMultipleLines(text)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n\n insertText(textarea, result)\n}\n\n/**\n * Apply multiline styling (quotes, task lists, etc)\n * Note: This does NOT expand selection to line - that should be done by the caller if needed\n */\nexport function multilineStyle(textarea, style) {\n const { prefix, suffix, surroundWithNewlines } = style\n let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n const lines = text.split('\\n')\n \n // Check if we need to undo (all lines have the format)\n const undoStyle = lines.every(line => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)))\n\n if (undoStyle) {\n // Remove the formatting\n text = lines.map(line => {\n let result = line.slice(prefix.length)\n if (suffix) {\n result = result.slice(0, result.length - suffix.length)\n }\n return result\n }).join('\\n')\n selectionEnd = selectionStart + text.length\n } else {\n // Apply the formatting\n text = lines.map(line => prefix + line + (suffix || '')).join('\\n')\n if (surroundWithNewlines) {\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n selectionStart += newlinesToAppend.length\n selectionEnd = selectionStart + text.length\n text = newlinesToAppend + text + newlinesToPrepend\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}", "/**\n * List operations for bullet and numbered lists\n */\n\nimport { expandSelectionToLine, newlinesToSurroundSelectedText, applyLineOperation } from '../core/selection.js'\nimport { insertText } from '../core/insertion.js'\n\n/**\n * Undo ordered list formatting\n */\nfunction undoOrderedListStyle(text) {\n const lines = text.split('\\n')\n const orderedListRegex = /^\\d+\\.\\s+/\n const shouldUndoOrderedList = lines.every(line => orderedListRegex.test(line))\n let result = lines\n if (shouldUndoOrderedList) {\n result = lines.map(line => line.replace(orderedListRegex, ''))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoOrderedList\n }\n}\n\n/**\n * Undo unordered list formatting\n */\nfunction undoUnorderedListStyle(text) {\n const lines = text.split('\\n')\n const unorderedListPrefix = '- '\n const shouldUndoUnorderedList = lines.every(line => line.startsWith(unorderedListPrefix))\n let result = lines\n if (shouldUndoUnorderedList) {\n result = lines.map(line => line.slice(unorderedListPrefix.length))\n }\n\n return {\n text: result.join('\\n'),\n processed: shouldUndoUnorderedList\n }\n}\n\n/**\n * Make prefix for list item\n */\nfunction makePrefix(index, unorderedList) {\n if (unorderedList) {\n return '- '\n } else {\n return `${index + 1}. `\n }\n}\n\n/**\n * Clear existing list style\n */\nfunction clearExistingListStyle(style, selectedText) {\n let undoResult\n let undoResultOppositeList\n let pristineText\n \n if (style.orderedList) {\n undoResult = undoOrderedListStyle(selectedText)\n undoResultOppositeList = undoUnorderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n } else {\n undoResult = undoUnorderedListStyle(selectedText)\n undoResultOppositeList = undoOrderedListStyle(undoResult.text)\n pristineText = undoResultOppositeList.text\n }\n \n return [undoResult, undoResultOppositeList, pristineText]\n}\n\n/**\n * Apply list styling to selected text\n */\nexport function listStyle(textarea, style) {\n const noInitialSelection = textarea.selectionStart === textarea.selectionEnd\n let selectionStart = textarea.selectionStart\n let selectionEnd = textarea.selectionEnd\n\n // Select whole line\n expandSelectionToLine(textarea)\n\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n\n // Clear any existing list formatting\n const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText)\n\n const prefixedLines = pristineText.split('\\n').map((value, index) => {\n return `${makePrefix(index, style.unorderedList)}${value}`\n })\n\n const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, style.unorderedList).length\n }, 0)\n\n const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {\n return previousValue + makePrefix(currentIndex, !style.unorderedList).length\n }, 0)\n\n // If we're undoing the same list type, just return the pristine text\n if (undoResult.processed) {\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart - makePrefix(0, style.unorderedList).length, 0)\n selectionEnd = selectionStart\n } else {\n selectionStart = textarea.selectionStart\n selectionEnd = textarea.selectionEnd - totalPrefixLength\n }\n return { text: pristineText, selectionStart, selectionEnd }\n }\n\n // Apply new list formatting\n const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea)\n const text = newlinesToAppend + prefixedLines.join('\\n') + newlinesToPrepend\n\n if (noInitialSelection) {\n selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0)\n selectionEnd = selectionStart\n } else {\n if (undoResultOppositeList.processed) {\n // Converting from one list type to another\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList\n } else {\n // Adding list formatting to plain text\n selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0)\n selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength\n }\n }\n\n return { text, selectionStart, selectionEnd }\n}\n\n/**\n * Apply list style to textarea\n */\nexport function applyListStyle(textarea, style) {\n // Use applyLineOperation for consistent selection preservation\n const result = applyLineOperation(\n textarea,\n (ta) => listStyle(ta, style),\n {\n // Custom selection adjustment for lists\n adjustSelection: (isRemoving, selStart, selEnd, lineStart) => {\n // Get the current line to check if we're removing\n const currentLine = textarea.value.slice(lineStart, textarea.selectionEnd)\n const orderedListRegex = /^\\d+\\.\\s+/\n const unorderedListRegex = /^- /\n \n // Check if we're removing a list\n const hasOrderedList = orderedListRegex.test(currentLine)\n const hasUnorderedList = unorderedListRegex.test(currentLine)\n const isRemovingCurrent = (style.orderedList && hasOrderedList) || (style.unorderedList && hasUnorderedList)\n \n if (selStart === selEnd) {\n // No selection - cursor position\n if (isRemovingCurrent) {\n // Removing list - adjust cursor back\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selStart - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selStart + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selStart + prefixLength\n }\n }\n } else {\n // Has selection - preserve it\n if (isRemovingCurrent) {\n // Removing current list type\n const prefixMatch = currentLine.match(style.orderedList ? orderedListRegex : unorderedListRegex)\n const prefixLength = prefixMatch ? prefixMatch[0].length : 0\n return {\n start: Math.max(selStart - prefixLength, lineStart),\n end: Math.max(selEnd - prefixLength, lineStart)\n }\n } else if (hasOrderedList || hasUnorderedList) {\n // Converting from one list type to another\n const oldPrefixMatch = currentLine.match(hasOrderedList ? orderedListRegex : unorderedListRegex)\n const oldPrefixLength = oldPrefixMatch ? oldPrefixMatch[0].length : 0\n const newPrefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n const adjustment = newPrefixLength - oldPrefixLength\n return {\n start: selStart + adjustment,\n end: selEnd + adjustment\n }\n } else {\n // Adding new list\n const prefixLength = style.unorderedList ? 2 : 3 // \"- \" or \"1. \"\n return {\n start: selStart + prefixLength,\n end: selEnd + prefixLength\n }\n }\n }\n }\n }\n )\n \n insertText(textarea, result)\n}", "/**\n * Format detection utilities\n */\n\nimport { FORMATS } from './formats.js'\n\n/**\n * Check if text has a specific format applied\n */\nfunction hasFormatApplied(text, format) {\n if (!format.prefix) return false\n \n if (format.suffix) {\n return text.startsWith(format.prefix) && text.endsWith(format.suffix)\n } else {\n return text.startsWith(format.prefix)\n }\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n if (!textarea) return []\n \n const formats = []\n const { selectionStart, selectionEnd, value } = textarea\n \n // Get current line for line-based formats\n const lines = value.split('\\n')\n let lineStart = 0\n let currentLine = ''\n \n for (const line of lines) {\n if (selectionStart >= lineStart && selectionStart <= lineStart + line.length) {\n currentLine = line\n break\n }\n lineStart += line.length + 1\n }\n \n // Check line-based formats\n if (currentLine.startsWith('- ')) {\n if (currentLine.startsWith('- [ ] ') || currentLine.startsWith('- [x] ')) {\n formats.push('task-list')\n } else {\n formats.push('bullet-list')\n }\n }\n \n if (/^\\d+\\.\\s/.test(currentLine)) {\n formats.push('numbered-list')\n }\n \n if (currentLine.startsWith('> ')) {\n formats.push('quote')\n }\n \n if (currentLine.startsWith('# ')) formats.push('header')\n if (currentLine.startsWith('## ')) formats.push('header-2')\n if (currentLine.startsWith('### ')) formats.push('header-3')\n \n // Check inline formats by looking around cursor\n const lookBehind = Math.max(0, selectionStart - 10)\n const lookAhead = Math.min(value.length, selectionEnd + 10)\n const surrounding = value.slice(lookBehind, lookAhead)\n \n // Check for bold\n if (surrounding.includes('**')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBold = beforeCursor.lastIndexOf('**')\n const nextCloseBold = afterCursor.indexOf('**')\n if (lastOpenBold !== -1 && nextCloseBold !== -1) {\n formats.push('bold')\n }\n }\n \n // Check for italic\n if (surrounding.includes('_')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenItalic = beforeCursor.lastIndexOf('_')\n const nextCloseItalic = afterCursor.indexOf('_')\n if (lastOpenItalic !== -1 && nextCloseItalic !== -1) {\n formats.push('italic')\n }\n }\n \n // Check for code\n if (surrounding.includes('`')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n if (beforeCursor.includes('`') && afterCursor.includes('`')) {\n formats.push('code')\n }\n }\n \n // Check for link\n if (surrounding.includes('[') && surrounding.includes(']')) {\n const beforeCursor = value.slice(Math.max(0, selectionStart - 100), selectionStart)\n const afterCursor = value.slice(selectionEnd, Math.min(value.length, selectionEnd + 100))\n const lastOpenBracket = beforeCursor.lastIndexOf('[')\n const nextCloseBracket = afterCursor.indexOf(']')\n if (lastOpenBracket !== -1 && nextCloseBracket !== -1) {\n const afterBracket = value.slice(selectionEnd + nextCloseBracket + 1, selectionEnd + nextCloseBracket + 10)\n if (afterBracket.startsWith('(')) {\n formats.push('link')\n }\n }\n }\n \n return formats\n}\n\n/**\n * Check if specific format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n const activeFormats = getActiveFormats(textarea)\n return activeFormats.includes(format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n if (!textarea) return\n \n const { toWord, toLine, toFormat } = options\n const { selectionStart, selectionEnd, value } = textarea\n \n if (toLine) {\n // Find line boundaries\n const lines = value.split('\\n')\n let lineStart = 0\n let lineEnd = 0\n let currentPos = 0\n \n for (const line of lines) {\n if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {\n lineStart = currentPos\n lineEnd = currentPos + line.length\n break\n }\n currentPos += line.length + 1\n }\n \n textarea.selectionStart = lineStart\n textarea.selectionEnd = lineEnd\n } else if (toWord && selectionStart === selectionEnd) {\n // Find word boundaries\n let start = selectionStart\n let end = selectionEnd\n \n // Move start back to word boundary\n while (start > 0 && !/\\s/.test(value[start - 1])) {\n start--\n }\n \n // Move end forward to word boundary\n while (end < value.length && !/\\s/.test(value[end])) {\n end++\n }\n \n textarea.selectionStart = start\n textarea.selectionEnd = end\n }\n}", "/**\n * markdown-actions - Lightweight markdown toolbar functionality\n * Based on GitHub's markdown-toolbar-element\n */\n\nimport { FORMATS, mergeWithDefaults } from './core/formats.js'\nimport { insertText, setUndoMethod } from './core/insertion.js'\nimport { preserveSelection, isMultipleLines, expandSelectionToLine, applyLineOperation } from './core/selection.js'\nimport { blockStyle, multilineStyle } from './operations/block.js'\nimport { applyListStyle } from './operations/list.js'\nimport { getActiveFormats as getActive, hasFormat as has, expandSelection as expand } from './core/detection.js'\nimport { debugLog, debugSelection, debugResult, setDebugMode, getDebugMode } from './debug.js'\n\n/**\n * Toggle bold formatting\n */\nexport function toggleBold(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleBold', 'Starting');\n debugSelection(textarea, 'Before');\n \n const style = mergeWithDefaults(FORMATS.bold)\n const result = blockStyle(textarea, style)\n \n debugResult(result);\n \n insertText(textarea, result)\n \n debugSelection(textarea, 'After');\n}\n\n/**\n * Toggle italic formatting\n */\nexport function toggleItalic(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.italic)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle code formatting\n */\nexport function toggleCode(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n // blockStyle already handles both inline and block code correctly\n const style = mergeWithDefaults(FORMATS.code)\n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle link formatting\n */\nexport function insertLink(textarea, options = {}) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n let style = mergeWithDefaults(FORMATS.link)\n \n // Check if selected text is a URL\n const isURL = selectedText && selectedText.match(/^https?:\\/\\//)\n \n if (isURL && !options.url) {\n // If selected text is a URL, use it as both link text and URL\n style.suffix = `](${selectedText})`\n style.replaceNext = ''\n // Don't change the selected text, it becomes the link text\n } else if (options.url) {\n // Override with custom URL if provided\n style.suffix = `](${options.url})`\n style.replaceNext = ''\n }\n \n // Override with custom text if provided\n if (options.text && !selectedText) {\n // Insert the text and select it\n const pos = textarea.selectionStart\n textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos)\n textarea.selectionStart = pos\n textarea.selectionEnd = pos + options.text.length\n }\n \n const result = blockStyle(textarea, style)\n insertText(textarea, result)\n}\n\n/**\n * Toggle bullet list formatting\n */\nexport function toggleBulletList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.bulletList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle numbered list formatting\n */\nexport function toggleNumberedList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n const style = mergeWithDefaults(FORMATS.numberedList)\n applyListStyle(textarea, style)\n}\n\n/**\n * Toggle quote formatting\n * Matches GitHub's implementation for quotes\n */\nexport function toggleQuote(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n debugLog('toggleQuote', 'Starting');\n debugSelection(textarea, 'Initial');\n \n const style = mergeWithDefaults(FORMATS.quote)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n debugResult(result);\n insertText(textarea, result)\n debugSelection(textarea, 'Final');\n}\n\n/**\n * Toggle task list formatting\n * Matches GitHub's implementation for task lists\n */\nexport function toggleTaskList(textarea) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(FORMATS.taskList)\n \n // Use the reusable line operation helper\n const result = applyLineOperation(\n textarea,\n (ta) => multilineStyle(ta, style),\n { prefix: style.prefix }\n )\n \n insertText(textarea, result)\n}\n\n/**\n * Insert or toggle header with specific level\n */\nexport function insertHeader(textarea, level = 1, toggle = false) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n if (level < 1 || level > 6) level = 1\n \n debugLog('insertHeader', `============ START ============`);\n debugLog('insertHeader', `Level: ${level}, Toggle: ${toggle}`);\n debugLog('insertHeader', `Initial cursor: ${textarea.selectionStart}-${textarea.selectionEnd}`);\n \n const headerKey = `header${level === 1 ? '1' : level}`\n const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1)\n debugLog('insertHeader', `Style prefix: \"${style.prefix}\"`);\n \n // Save original positions and get line info BEFORE applyLineOperation\n const value = textarea.value\n const originalStart = textarea.selectionStart\n const originalEnd = textarea.selectionEnd\n \n // Find the current line boundaries to check existing header\n let lineStart = originalStart\n while (lineStart > 0 && value[lineStart - 1] !== '\\n') {\n lineStart--\n }\n let lineEnd = originalEnd\n while (lineEnd < value.length && value[lineEnd] !== '\\n') {\n lineEnd++\n }\n \n // Get current line and check for existing header\n const currentLineContent = value.slice(lineStart, lineEnd)\n debugLog('insertHeader', `Current line (before): \"${currentLineContent}\"`);\n \n const existingHeaderMatch = currentLineContent.match(/^(#{1,6})\\s*/)\n const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0\n const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0\n \n debugLog('insertHeader', `Existing header check:`);\n debugLog('insertHeader', ` - Match: ${existingHeaderMatch ? `\"${existingHeaderMatch[0]}\"` : 'none'}`);\n debugLog('insertHeader', ` - Existing level: ${existingLevel}`);\n debugLog('insertHeader', ` - Existing prefix length: ${existingPrefixLength}`);\n debugLog('insertHeader', ` - Target level: ${level}`);\n \n // Determine if we're toggling off\n const shouldToggleOff = toggle && existingLevel === level\n debugLog('insertHeader', `Should toggle OFF: ${shouldToggleOff} (toggle=${toggle}, existingLevel=${existingLevel}, level=${level})`);\n \n // Use applyLineOperation for consistent behavior\n const result = applyLineOperation(\n textarea,\n (ta) => {\n const currentLine = ta.value.slice(ta.selectionStart, ta.selectionEnd)\n debugLog('insertHeader', `Line in operation: \"${currentLine}\"`);\n \n // Remove any existing header formatting\n const cleanedLine = currentLine.replace(/^#{1,6}\\s*/, '')\n debugLog('insertHeader', `Cleaned line: \"${cleanedLine}\"`);\n \n let newLine\n \n if (shouldToggleOff) {\n // Toggle off - just use the cleaned line\n debugLog('insertHeader', 'ACTION: Toggling OFF - removing header');\n newLine = cleanedLine\n } else if (existingLevel > 0) {\n // Replace existing header with new one\n debugLog('insertHeader', `ACTION: Replacing H${existingLevel} with H${level}`);\n newLine = style.prefix + cleanedLine\n } else {\n // Add new header\n debugLog('insertHeader', 'ACTION: Adding new header');\n newLine = style.prefix + cleanedLine\n }\n \n debugLog('insertHeader', `New line: \"${newLine}\"`);\n \n return {\n text: newLine,\n selectionStart: ta.selectionStart,\n selectionEnd: ta.selectionEnd\n }\n },\n {\n prefix: style.prefix,\n // Custom selection adjustment for headers\n adjustSelection: (isRemoving, selStart, selEnd, lineStartPos) => {\n debugLog('insertHeader', `Adjusting selection:`);\n debugLog('insertHeader', ` - isRemoving param: ${isRemoving}`);\n debugLog('insertHeader', ` - shouldToggleOff: ${shouldToggleOff}`);\n debugLog('insertHeader', ` - selStart: ${selStart}, selEnd: ${selEnd}`);\n debugLog('insertHeader', ` - lineStartPos: ${lineStartPos}`);\n \n if (shouldToggleOff) {\n // Removing the header entirely\n const adjustment = Math.max(selStart - existingPrefixLength, lineStartPos)\n debugLog('insertHeader', ` - Removing header, adjusting by -${existingPrefixLength}`);\n return {\n start: adjustment,\n end: selStart === selEnd ? adjustment : Math.max(selEnd - existingPrefixLength, lineStartPos)\n }\n } else if (existingPrefixLength > 0) {\n // Replacing existing header with new one\n const prefixDiff = style.prefix.length - existingPrefixLength\n debugLog('insertHeader', ` - Replacing header, adjusting by ${prefixDiff}`);\n return {\n start: selStart + prefixDiff,\n end: selEnd + prefixDiff\n }\n } else {\n // Adding new header\n debugLog('insertHeader', ` - Adding header, adjusting by +${style.prefix.length}`);\n return {\n start: selStart + style.prefix.length,\n end: selEnd + style.prefix.length\n }\n }\n }\n }\n )\n \n debugLog('insertHeader', `Final result: text=\"${result.text}\", cursor=${result.selectionStart}-${result.selectionEnd}`);\n debugLog('insertHeader', `============ END ============`);\n \n insertText(textarea, result)\n}\n\n/**\n * Toggle H1 header\n */\nexport function toggleH1(textarea) {\n insertHeader(textarea, 1, true)\n}\n\n/**\n * Toggle H2 header\n */\nexport function toggleH2(textarea) {\n insertHeader(textarea, 2, true)\n}\n\n/**\n * Toggle H3 header\n */\nexport function toggleH3(textarea) {\n insertHeader(textarea, 3, true)\n}\n\n/**\n * Get active formats at cursor position\n */\nexport function getActiveFormats(textarea) {\n return getActive(textarea)\n}\n\n/**\n * Check if format is active at cursor\n */\nexport function hasFormat(textarea, format) {\n return has(textarea, format)\n}\n\n/**\n * Expand selection based on options\n */\nexport function expandSelection(textarea, options = {}) {\n expand(textarea, options)\n}\n\n/**\n * Apply custom format\n */\nexport function applyCustomFormat(textarea, format) {\n if (!textarea || textarea.disabled || textarea.readOnly) return\n \n const style = mergeWithDefaults(format)\n let result\n \n if (style.multiline) {\n const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd)\n if (isMultipleLines(selectedText)) {\n result = multilineStyle(textarea, style)\n } else {\n result = blockStyle(textarea, style)\n }\n } else {\n result = blockStyle(textarea, style)\n }\n \n insertText(textarea, result)\n}\n\n/**\n * Preserve selection during callback\n */\nexport { preserveSelection }\n\n/**\n * Configure undo method\n */\nexport { setUndoMethod }\n\n/**\n * Debug mode control\n */\nexport { setDebugMode, getDebugMode }\n\n/**\n * Default export with all functions\n */\nexport default {\n toggleBold,\n toggleItalic,\n toggleCode,\n insertLink,\n toggleBulletList,\n toggleNumberedList,\n toggleQuote,\n toggleTaskList,\n insertHeader,\n toggleH1,\n toggleH2,\n toggleH3,\n getActiveFormats,\n hasFormat,\n expandSelection,\n applyCustomFormat,\n preserveSelection,\n setUndoMethod,\n setDebugMode,\n getDebugMode\n}", "/**\n * Toolbar component for OverType editor\n * Provides markdown formatting buttons with support for custom buttons\n */\n\nimport * as markdownActions from 'markdown-actions';\n\nexport class Toolbar {\n constructor(editor, options = {}) {\n this.editor = editor;\n this.container = null;\n this.buttons = {};\n\n // Get toolbar buttons array\n this.toolbarButtons = options.toolbarButtons || [];\n }\n\n /**\n * Create and render toolbar\n */\n create() {\n this.container = document.createElement('div');\n this.container.className = 'overtype-toolbar';\n this.container.setAttribute('role', 'toolbar');\n this.container.setAttribute('aria-label', 'Formatting toolbar');\n\n // Create buttons from toolbarButtons array\n this.toolbarButtons.forEach(buttonConfig => {\n if (buttonConfig.name === 'separator') {\n const separator = this.createSeparator();\n this.container.appendChild(separator);\n } else {\n const button = this.createButton(buttonConfig);\n this.buttons[buttonConfig.name] = button;\n this.container.appendChild(button);\n }\n });\n\n // Insert toolbar before the wrapper (as sibling, not child)\n this.editor.container.insertBefore(this.container, this.editor.wrapper);\n }\n\n /**\n * Create a toolbar separator\n */\n createSeparator() {\n const separator = document.createElement('div');\n separator.className = 'overtype-toolbar-separator';\n separator.setAttribute('role', 'separator');\n return separator;\n }\n\n /**\n * Create a toolbar button\n */\n createButton(buttonConfig) {\n const button = document.createElement('button');\n button.className = 'overtype-toolbar-button';\n button.type = 'button';\n button.setAttribute('data-button', buttonConfig.name);\n button.title = buttonConfig.title || '';\n button.setAttribute('aria-label', buttonConfig.title || buttonConfig.name);\n button.innerHTML = this.sanitizeSVG(buttonConfig.icon || '');\n\n // Special handling for viewMode dropdown\n if (buttonConfig.name === 'viewMode') {\n button.classList.add('has-dropdown');\n button.dataset.dropdown = 'true';\n button.addEventListener('click', (e) => {\n e.preventDefault();\n this.toggleViewModeDropdown(button);\n });\n return button;\n }\n\n // Standard button click handler - delegate to performAction\n button._clickHandler = (e) => {\n e.preventDefault();\n const actionId = buttonConfig.actionId || buttonConfig.name;\n this.editor.performAction(actionId, e);\n };\n\n button.addEventListener('click', button._clickHandler);\n return button;\n }\n\n /**\n * Handle button action programmatically\n * Accepts either an actionId string or a buttonConfig object (backwards compatible)\n * @param {string|Object} actionIdOrConfig - Action identifier string or button config object\n * @returns {Promise} Whether the action was executed\n */\n async handleAction(actionIdOrConfig) {\n // Old style: buttonConfig object with .action function - execute directly\n if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {\n this.editor.textarea.focus();\n try {\n await actionIdOrConfig.action({\n editor: this.editor,\n getValue: () => this.editor.getValue(),\n setValue: (value) => this.editor.setValue(value),\n event: null\n });\n return true;\n } catch (error) {\n console.error(`Action \"${actionIdOrConfig.name}\" error:`, error);\n this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {\n detail: { buttonName: actionIdOrConfig.name, error }\n }));\n return false;\n }\n }\n\n // New style: string actionId - delegate to performAction\n if (typeof actionIdOrConfig === 'string') {\n return this.editor.performAction(actionIdOrConfig, null);\n }\n\n return false;\n }\n\n /**\n * Sanitize SVG to prevent XSS\n */\n sanitizeSVG(svg) {\n if (typeof svg !== 'string') return '';\n\n // Remove script tags and on* event handlers\n const cleaned = svg\n .replace(/)<[^<]*)*<\\/script>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[\"'][^\"']*[\"']/gi, '')\n .replace(/\\son\\w+\\s*=\\s*[^\\s>]*/gi, '');\n\n return cleaned;\n }\n\n /**\n * Toggle view mode dropdown (internal implementation)\n * Not exposed to users - viewMode button behavior is fixed\n */\n toggleViewModeDropdown(button) {\n // Close any existing dropdown\n const existingDropdown = document.querySelector('.overtype-dropdown-menu');\n if (existingDropdown) {\n existingDropdown.remove();\n button.classList.remove('dropdown-active');\n return;\n }\n\n button.classList.add('dropdown-active');\n\n const dropdown = this.createViewModeDropdown(button);\n\n // Position dropdown relative to button\n const rect = button.getBoundingClientRect();\n dropdown.style.position = 'absolute';\n dropdown.style.top = `${rect.bottom + 5}px`;\n dropdown.style.left = `${rect.left}px`;\n\n document.body.appendChild(dropdown);\n\n // Click outside to close\n this.handleDocumentClick = (e) => {\n if (!dropdown.contains(e.target) && !button.contains(e.target)) {\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n }\n };\n\n setTimeout(() => {\n document.addEventListener('click', this.handleDocumentClick);\n }, 0);\n }\n\n /**\n * Create view mode dropdown menu (internal implementation)\n */\n createViewModeDropdown(button) {\n const dropdown = document.createElement('div');\n dropdown.className = 'overtype-dropdown-menu';\n\n const items = [\n { id: 'normal', label: 'Normal Edit', icon: '\u2713' },\n { id: 'plain', label: 'Plain Textarea', icon: '\u2713' },\n { id: 'preview', label: 'Preview Mode', icon: '\u2713' }\n ];\n\n const currentMode = this.editor.container.dataset.mode || 'normal';\n\n items.forEach(item => {\n const menuItem = document.createElement('button');\n menuItem.className = 'overtype-dropdown-item';\n menuItem.type = 'button';\n menuItem.textContent = item.label;\n\n if (item.id === currentMode) {\n menuItem.classList.add('active');\n menuItem.setAttribute('aria-current', 'true');\n const checkmark = document.createElement('span');\n checkmark.className = 'overtype-dropdown-icon';\n checkmark.textContent = item.icon;\n menuItem.prepend(checkmark);\n }\n\n menuItem.addEventListener('click', (e) => {\n e.preventDefault();\n\n // Handle view mode changes\n switch(item.id) {\n case 'plain':\n this.editor.showPlainTextarea();\n break;\n case 'preview':\n this.editor.showPreviewMode();\n break;\n case 'normal':\n default:\n this.editor.showNormalEditMode();\n break;\n }\n\n dropdown.remove();\n button.classList.remove('dropdown-active');\n document.removeEventListener('click', this.handleDocumentClick);\n });\n\n dropdown.appendChild(menuItem);\n });\n\n return dropdown;\n }\n\n /**\n * Update active states of toolbar buttons\n */\n updateButtonStates() {\n try {\n const activeFormats = markdownActions.getActiveFormats?.(\n this.editor.textarea,\n this.editor.textarea.selectionStart\n ) || [];\n\n Object.entries(this.buttons).forEach(([name, button]) => {\n if (name === 'viewMode') return; // Skip dropdown button\n\n let isActive = false;\n\n switch(name) {\n case 'bold':\n isActive = activeFormats.includes('bold');\n break;\n case 'italic':\n isActive = activeFormats.includes('italic');\n break;\n case 'code':\n isActive = false; // Disabled: unreliable in code blocks\n break;\n case 'bulletList':\n isActive = activeFormats.includes('bullet-list');\n break;\n case 'orderedList':\n isActive = activeFormats.includes('numbered-list');\n break;\n case 'taskList':\n isActive = activeFormats.includes('task-list');\n break;\n case 'quote':\n isActive = activeFormats.includes('quote');\n break;\n case 'h1':\n isActive = activeFormats.includes('header');\n break;\n case 'h2':\n isActive = activeFormats.includes('header-2');\n break;\n case 'h3':\n isActive = activeFormats.includes('header-3');\n break;\n }\n\n button.classList.toggle('active', isActive);\n button.setAttribute('aria-pressed', isActive.toString());\n });\n } catch (error) {\n // Silently fail if markdown-actions not available\n }\n }\n\n /**\n * Destroy toolbar and cleanup\n */\n destroy() {\n if (this.container) {\n // Clean up event listeners\n if (this.handleDocumentClick) {\n document.removeEventListener('click', this.handleDocumentClick);\n }\n\n // Clean up button listeners\n Object.values(this.buttons).forEach(button => {\n if (button._clickHandler) {\n button.removeEventListener('click', button._clickHandler);\n delete button._clickHandler;\n }\n });\n\n // Remove container\n this.container.remove();\n this.container = null;\n this.buttons = {};\n }\n }\n}\n", "/**\n * Link Tooltip - CSS Anchor Positioning with Floating UI fallback\n * Shows a clickable tooltip when cursor is within a link\n * Uses CSS anchor positioning for modern browsers, Floating UI for older browsers\n */\n\nexport class LinkTooltip {\n constructor(editor) {\n this.editor = editor;\n this.tooltip = null;\n this.currentLink = null;\n this.hideTimeout = null;\n this.visibilityChangeHandler = null;\n this.useFloatingUI = false;\n this.floatingUI = null;\n this.isTooltipHovered = false;\n\n this.init();\n }\n\n async init() {\n // Detect CSS anchor positioning support\n const supportsAnchorPositioning = CSS.supports('position-anchor: --x') &&\n CSS.supports('position-area: center');\n\n // Load Floating UI if needed\n if (!supportsAnchorPositioning) {\n try {\n // Use indirect eval to prevent bundler from processing the import\n const importFn = new Function('url', 'return import(url)');\n const { computePosition, offset, shift, flip } = await importFn(\n 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm'\n );\n this.floatingUI = { computePosition, offset, shift, flip };\n this.useFloatingUI = true;\n } catch (error) {\n // If dynamic import fails, tooltips simply won't show\n console.warn('Failed to load Floating UI fallback:', error);\n this.floatingUI = null;\n this.useFloatingUI = false;\n }\n }\n\n // Create tooltip element\n // Note: Styles are now in the main stylesheet (styles.js) with @supports wrapper\n this.createTooltip();\n\n // Listen for cursor position changes\n this.editor.textarea.addEventListener('selectionchange', () => this.checkCursorPosition());\n this.editor.textarea.addEventListener('keyup', e => {\n if (e.key.includes('Arrow') || e.key === 'Home' || e.key === 'End') {\n this.checkCursorPosition();\n }\n });\n\n // Hide tooltip when typing\n this.editor.textarea.addEventListener('input', () => this.hide());\n\n // Reposition or hide tooltip when scrolling\n this.editor.textarea.addEventListener('scroll', () => {\n if (this.useFloatingUI && this.currentLink) {\n // Reposition the tooltip for Floating UI\n this.showWithFloatingUI(this.currentLink);\n } else {\n // Hide for CSS anchor positioning (native browser behavior handles this)\n this.hide();\n }\n });\n\n // Hide tooltip when textarea loses focus (unless hovering tooltip)\n this.editor.textarea.addEventListener('blur', () => {\n if (!this.isTooltipHovered) {\n this.hide();\n }\n });\n\n // Hide tooltip when page loses visibility (tab switch, minimize, etc.)\n this.visibilityChangeHandler = () => {\n if (document.hidden) {\n this.hide();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n\n // Track hover state to prevent hiding when clicking tooltip\n this.tooltip.addEventListener('mouseenter', () => {\n this.isTooltipHovered = true;\n this.cancelHide();\n });\n this.tooltip.addEventListener('mouseleave', () => {\n this.isTooltipHovered = false;\n this.scheduleHide();\n });\n }\n\n createTooltip() {\n // Create tooltip element\n // Styles are now included in the main stylesheet (styles.js)\n this.tooltip = document.createElement('div');\n this.tooltip.className = 'overtype-link-tooltip';\n\n // Add link icon and text container\n this.tooltip.innerHTML = `\n \n \n \n \n \n \n \n `;\n\n // Click handler to open link\n this.tooltip.addEventListener('click', e => {\n e.preventDefault();\n e.stopPropagation();\n if (this.currentLink) {\n window.open(this.currentLink.url, '_blank');\n this.hide();\n }\n });\n\n // Append tooltip to editor container\n this.editor.container.appendChild(this.tooltip);\n }\n\n checkCursorPosition() {\n const cursorPos = this.editor.textarea.selectionStart;\n const text = this.editor.textarea.value;\n\n // Find if cursor is within a markdown link\n const linkInfo = this.findLinkAtPosition(text, cursorPos);\n\n if (linkInfo) {\n if (!this.currentLink || this.currentLink.url !== linkInfo.url || this.currentLink.index !== linkInfo.index) {\n this.show(linkInfo);\n }\n } else {\n this.scheduleHide();\n }\n }\n\n findLinkAtPosition(text, position) {\n // Regex to find markdown links: [text](url)\n const linkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n let match;\n let linkIndex = 0;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const start = match.index;\n const end = match.index + match[0].length;\n\n if (position >= start && position <= end) {\n return {\n text: match[1],\n url: match[2],\n index: linkIndex,\n start: start,\n end: end\n };\n }\n linkIndex++;\n }\n\n return null;\n }\n\n show(linkInfo) {\n this.currentLink = linkInfo;\n this.cancelHide();\n\n // Update tooltip content\n const urlSpan = this.tooltip.querySelector('.overtype-link-tooltip-url');\n urlSpan.textContent = linkInfo.url;\n\n if (this.useFloatingUI) {\n this.showWithFloatingUI(linkInfo);\n } else {\n this.showWithAnchorPositioning(linkInfo);\n }\n\n this.tooltip.classList.add('visible');\n }\n\n showWithAnchorPositioning(linkInfo) {\n // Set the CSS variable to point to the correct anchor\n this.tooltip.style.setProperty('--target-anchor', `--link-${linkInfo.index}`);\n }\n\n async showWithFloatingUI(linkInfo) {\n // Find the element in preview that corresponds to this link\n const anchorElement = this.findAnchorElement(linkInfo.index);\n\n if (!anchorElement) {\n return;\n }\n\n // Check if anchor element is visible and in viewport\n const rect = anchorElement.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) {\n return;\n }\n\n try {\n // Compute position using Floating UI\n const { x, y } = await this.floatingUI.computePosition(\n anchorElement,\n this.tooltip,\n {\n placement: 'bottom',\n middleware: [\n this.floatingUI.offset(8),\n this.floatingUI.shift({ padding: 8 }),\n this.floatingUI.flip()\n ]\n }\n );\n\n // Apply position\n Object.assign(this.tooltip.style, {\n left: `${x}px`,\n top: `${y}px`,\n position: 'absolute'\n });\n } catch (error) {\n // If Floating UI computation fails, don't show tooltip\n console.warn('Floating UI positioning failed:', error);\n return;\n }\n }\n\n findAnchorElement(linkIndex) {\n // Find the element with the matching anchor-name style\n const preview = this.editor.preview;\n // Direct query for the specific link - more efficient than iterating\n return preview.querySelector(`a[style*=\"--link-${linkIndex}\"]`);\n }\n\n hide() {\n this.tooltip.classList.remove('visible');\n this.currentLink = null;\n this.isTooltipHovered = false;\n }\n\n scheduleHide() {\n this.cancelHide();\n this.hideTimeout = setTimeout(() => this.hide(), 300);\n }\n\n cancelHide() {\n if (this.hideTimeout) {\n clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n destroy() {\n this.cancelHide();\n\n // Remove visibility change listener\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.tooltip && this.tooltip.parentNode) {\n this.tooltip.parentNode.removeChild(this.tooltip);\n }\n this.tooltip = null;\n this.currentLink = null;\n this.floatingUI = null;\n this.useFloatingUI = false;\n this.isTooltipHovered = false;\n }\n}\n", "/**\n * SVG icons for OverType toolbar\n * Quill-style icons with inline styles\n */\n\nexport const boldIcon = `\n \n \n`;\n\nexport const italicIcon = `\n \n \n \n`;\n\nexport const h1Icon = `\n \n`;\n\nexport const h2Icon = `\n \n`;\n\nexport const h3Icon = `\n \n`;\n\nexport const linkIcon = `\n \n \n \n`;\n\nexport const codeIcon = `\n \n \n \n`;\n\n\nexport const bulletListIcon = `\n \n \n \n \n \n \n`;\n\nexport const orderedListIcon = `\n \n \n \n \n \n \n \n`;\n\nexport const quoteIcon = `\n \n \n`;\n\nexport const taskListIcon = `\n \n \n \n \n \n \n`;\n\nexport const eyeIcon = `\n \n \n`;", "/**\n * Toolbar button definitions for OverType editor\n * Export built-in buttons that can be used in custom toolbar configurations\n */\n\nimport * as icons from './icons.js';\nimport * as markdownActions from 'markdown-actions';\n\n/**\n * Built-in toolbar button definitions\n * Each button has: name, actionId, icon, title, action\n * - name: DOM identifier for the button element\n * - actionId: Canonical action identifier used by performAction\n * Action signature: ({ editor, getValue, setValue, event }) => void\n */\nexport const toolbarButtons = {\n bold: {\n name: 'bold',\n actionId: 'toggleBold',\n icon: icons.boldIcon,\n title: 'Bold (Ctrl+B)',\n action: ({ editor }) => {\n markdownActions.toggleBold(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n italic: {\n name: 'italic',\n actionId: 'toggleItalic',\n icon: icons.italicIcon,\n title: 'Italic (Ctrl+I)',\n action: ({ editor }) => {\n markdownActions.toggleItalic(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n code: {\n name: 'code',\n actionId: 'toggleCode',\n icon: icons.codeIcon,\n title: 'Inline Code',\n action: ({ editor }) => {\n markdownActions.toggleCode(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n separator: {\n name: 'separator'\n // No icon, title, or action - special separator element\n },\n\n link: {\n name: 'link',\n actionId: 'insertLink',\n icon: icons.linkIcon,\n title: 'Insert Link',\n action: ({ editor }) => {\n markdownActions.insertLink(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h1: {\n name: 'h1',\n actionId: 'toggleH1',\n icon: icons.h1Icon,\n title: 'Heading 1',\n action: ({ editor }) => {\n markdownActions.toggleH1(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h2: {\n name: 'h2',\n actionId: 'toggleH2',\n icon: icons.h2Icon,\n title: 'Heading 2',\n action: ({ editor }) => {\n markdownActions.toggleH2(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n h3: {\n name: 'h3',\n actionId: 'toggleH3',\n icon: icons.h3Icon,\n title: 'Heading 3',\n action: ({ editor }) => {\n markdownActions.toggleH3(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n bulletList: {\n name: 'bulletList',\n actionId: 'toggleBulletList',\n icon: icons.bulletListIcon,\n title: 'Bullet List',\n action: ({ editor }) => {\n markdownActions.toggleBulletList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n orderedList: {\n name: 'orderedList',\n actionId: 'toggleNumberedList',\n icon: icons.orderedListIcon,\n title: 'Numbered List',\n action: ({ editor }) => {\n markdownActions.toggleNumberedList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n taskList: {\n name: 'taskList',\n actionId: 'toggleTaskList',\n icon: icons.taskListIcon,\n title: 'Task List',\n action: ({ editor }) => {\n if (markdownActions.toggleTaskList) {\n markdownActions.toggleTaskList(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n }\n },\n\n quote: {\n name: 'quote',\n actionId: 'toggleQuote',\n icon: icons.quoteIcon,\n title: 'Quote',\n action: ({ editor }) => {\n markdownActions.toggleQuote(editor.textarea);\n editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));\n }\n },\n\n viewMode: {\n name: 'viewMode',\n icon: icons.eyeIcon,\n title: 'View mode'\n // Special: handled internally by Toolbar class as dropdown\n // No action property - dropdown behavior is internal\n }\n};\n\n/**\n * Default toolbar button layout with separators\n * This is used when toolbar: true but no toolbarButtons provided\n */\nexport const defaultToolbarButtons = [\n toolbarButtons.bold,\n toolbarButtons.italic,\n toolbarButtons.code,\n toolbarButtons.separator,\n toolbarButtons.link,\n toolbarButtons.separator,\n toolbarButtons.h1,\n toolbarButtons.h2,\n toolbarButtons.h3,\n toolbarButtons.separator,\n toolbarButtons.bulletList,\n toolbarButtons.orderedList,\n toolbarButtons.taskList,\n toolbarButtons.separator,\n toolbarButtons.quote,\n toolbarButtons.separator,\n toolbarButtons.viewMode\n];\n"], + "mappings": "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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmO3B,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAmaV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAiCV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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", "names": ["result", "debugMode", "getActiveFormats", "toolbarButtons"] } diff --git a/src/overtype.js b/src/overtype.js index d4a4536..f007017 100644 --- a/src/overtype.js +++ b/src/overtype.js @@ -80,11 +80,13 @@ class OverType { static stylesInjected = false; static globalListenersInitialized = false; static instanceCount = 0; - static _mq = null; // Shared media query for auto theme - static _mqListener = null; // Shared listener - static _autoInstances = new Set(); // Track auto-themed instances - static _globalAutoMq = null; // Global auto theme media query - static _globalAutoListener = null; // Global auto theme listener + // Instance-level auto theme tracking (when individual instances use auto theme) + static _mq = null; // Shared media query for instance auto themes + static _mqListener = null; // Shared listener for instance auto themes + static _autoInstances = new Set(); // Track instances using auto theme + // Global-level auto theme tracking (when OverType.setTheme('auto') is called) + static _globalAutoMq = null; // Media query for global auto theme + static _globalAutoListener = null; // Listener for global auto theme /** * Constructor - Always returns an array of instances @@ -1464,7 +1466,7 @@ class OverType { }); document.querySelectorAll('overtype-editor').forEach(wc => { - wc.setAttribute?.(isAuto ? 'theme' : 'theme', isAuto ? 'auto' : themeName); + wc.setAttribute?.('theme', isAuto ? 'auto' : themeName); if (isAuto) wc.setAttribute?.('data-resolved-theme', themeName); wc.refreshTheme?.(); }); From f8d77e3f7ae291d3e46e9e3aa73eb6a443c906df Mon Sep 17 00:00:00 2001 From: Deyan Gigov Date: Fri, 13 Feb 2026 21:34:55 +0200 Subject: [PATCH 8/8] Using the code from #94 to further save ~10KB in the min version. --- dist/overtype.min.js | 915 +------------------------------------------ 1 file changed, 4 insertions(+), 911 deletions(-) diff --git a/dist/overtype.min.js b/dist/overtype.min.js index 626767a..8b3b3a1 100644 --- a/dist/overtype.min.js +++ b/dist/overtype.min.js @@ -13,855 +13,11 @@ var OverType=(()=>{var O=Object.defineProperty;var Fe=Object.getOwnPropertyDescr `),i=0,r=0,s=0;for(let u=0;u=t){r=u,s=i;break}i+=m+1}let a=n[r],p=s+a.length,d=a.match(this.LIST_PATTERNS.checkbox);if(d)return{inList:!0,listType:"checkbox",indent:d[1],marker:"-",checked:d[2]==="x",content:d[3],lineStart:s,lineEnd:p,markerEndPos:s+d[1].length+d[2].length+5};let l=a.match(this.LIST_PATTERNS.bullet);if(l)return{inList:!0,listType:"bullet",indent:l[1],marker:l[2],content:l[3],lineStart:s,lineEnd:p,markerEndPos:s+l[1].length+l[2].length+1};let c=a.match(this.LIST_PATTERNS.numbered);return c?{inList:!0,listType:"numbered",indent:c[1],marker:parseInt(c[2]),content:c[3],lineStart:s,lineEnd:p,markerEndPos:s+c[1].length+c[2].length+2}:{inList:!1,listType:null,indent:"",marker:null,content:a,lineStart:s,lineEnd:p,markerEndPos:s}}static createNewListItem(e){switch(e.listType){case"bullet":return`${e.indent}${e.marker} `;case"numbered":return`${e.indent}${e.marker+1}. `;case"checkbox":return`${e.indent}- [ ] `;default:return""}}static renumberLists(e){let t=e.split(` `),n=new Map,i=!1;return t.map(s=>{let a=s.match(this.LIST_PATTERNS.numbered);if(a){let p=a[1],d=p.length,l=a[3];i||n.clear();let c=(n.get(d)||0)+1;n.set(d,c);for(let[u]of n)u>d&&n.delete(u);return i=!0,`${p}${c}. ${l}`}else return(s.trim()===""||!s.match(/^\s/))&&(i=!1,n.clear()),s}).join(` `)}};E(S,"linkIndex",0),E(S,"codeHighlighter",null),E(S,"customSyntax",null),E(S,"LIST_PATTERNS",{bullet:/^(\s*)([-*+])\s+(.*)$/,numbered:/^(\s*)(\d+)\.\s+(.*)$/,checkbox:/^(\s*)-\s+\[([ x])\]\s+(.*)$/});var z=class{constructor(e){this.editor=e}handleKeydown(e){if(!(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey))return!1;let i=null;switch(e.key.toLowerCase()){case"b":e.shiftKey||(i="toggleBold");break;case"i":e.shiftKey||(i="toggleItalic");break;case"k":e.shiftKey||(i="insertLink");break;case"7":e.shiftKey&&(i="toggleNumberedList");break;case"8":e.shiftKey&&(i="toggleBulletList");break}return i?(e.preventDefault(),this.editor.performAction(i,e),!0):!1}destroy(){}};var A={name:"solar",colors:{bgPrimary:"#faf0ca",bgSecondary:"#ffffff",text:"#0d3b66",textPrimary:"#0d3b66",textSecondary:"#5a7a9b",h1:"#f95738",h2:"#ee964b",h3:"#3d8a51",strong:"#ee964b",em:"#f95738",del:"#ee964b",link:"#0d3b66",code:"#0d3b66",codeBg:"rgba(244, 211, 94, 0.4)",blockquote:"#5a7a9b",hr:"#5a7a9b",syntaxMarker:"rgba(13, 59, 102, 0.52)",syntax:"#999999",cursor:"#f95738",selection:"rgba(244, 211, 94, 0.4)",listMarker:"#ee964b",rawLine:"#5a7a9b",border:"#e0e0e0",hoverBg:"#f0f0f0",primary:"#0d3b66",toolbarBg:"#ffffff",toolbarIcon:"#0d3b66",toolbarHover:"#f5f5f5",toolbarActive:"#faf0ca"}},ee={name:"cave",colors:{bgPrimary:"#141E26",bgSecondary:"#1D2D3E",text:"#c5dde8",textPrimary:"#c5dde8",textSecondary:"#9fcfec",h1:"#d4a5ff",h2:"#f6ae2d",h3:"#9fcfec",strong:"#f6ae2d",em:"#9fcfec",del:"#f6ae2d",link:"#9fcfec",code:"#c5dde8",codeBg:"#1a232b",blockquote:"#9fcfec",hr:"#c5dde8",syntaxMarker:"rgba(159, 207, 236, 0.73)",syntax:"#7a8c98",cursor:"#f26419",selection:"rgba(51, 101, 138, 0.4)",listMarker:"#f6ae2d",rawLine:"#9fcfec",border:"#2a3f52",hoverBg:"#243546",primary:"#9fcfec",toolbarBg:"#1D2D3E",toolbarIcon:"#c5dde8",toolbarHover:"#243546",toolbarActive:"#2a3f52"}},We={name:"auto",colors:A.colors},te={solar:A,cave:ee,auto:We,light:A,dark:ee};function M(o){return typeof o=="string"?{...te[o]||te.solar,name:o}:o}var j=null;function K(o){return o!=="auto"?o:(!j&&window.matchMedia&&(j=window.matchMedia("(prefers-color-scheme: dark)")),j!=null&&j.matches?"cave":"solar")}function _(o){let e=[];for(let[t,n]of Object.entries(o)){let i=t.replace(/([A-Z])/g,"-$1").toLowerCase();e.push(`--${i}: ${n};`)}return e.join(` -`)}function G(o,e={}){return{...o,colors:{...o.colors,...e}}}function ne(o={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:n='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:s={}}=o,a=Object.keys(s).length>0?` - @media (max-width: 640px) { - .overtype-wrapper .overtype-input, - .overtype-wrapper .overtype-preview { - ${Object.entries(s).map(([d,l])=>`${d.replace(/([A-Z])/g,"-$1").toLowerCase()}: ${l} !important;`).join(` +`)}function G(o,e={}){return{...o,colors:{...o.colors,...e}}}function ne(o={}){let{fontSize:e="14px",lineHeight:t=1.6,fontFamily:n='"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:i="20px",theme:r=null,mobile:s={}}=o,a=Object.keys(s).length>0?` @media (max-width:640px){.overtype-wrapper .overtype-input,.overtype-wrapper .overtype-preview{${Object.entries(s).map(([d,l])=>`${d.replace(/([A-Z])/g,"-$1").toLowerCase()}: ${l} !important;`).join(` `)} } } - `:"",p=r&&r.colors?_(r.colors):"";return` - /* OverType Editor Styles */ - - /* Middle-ground CSS Reset - Prevent parent styles from leaking in */ - .overtype-container * { - /* Box model - these commonly leak */ - margin: 0 !important; - padding: 0 !important; - border: 0 !important; - - /* Layout - these can break our layout */ - /* Don't reset position - it breaks dropdowns */ - float: none !important; - clear: none !important; - - /* Typography - only reset decorative aspects */ - text-decoration: none !important; - text-transform: none !important; - letter-spacing: normal !important; - - /* Visual effects that can interfere */ - box-shadow: none !important; - text-shadow: none !important; - - /* Ensure box-sizing is consistent */ - box-sizing: border-box !important; - - /* Keep inheritance for these */ - /* font-family, color, line-height, font-size - inherit */ - } - - /* Container base styles after reset */ - .overtype-container { - display: flex !important; - flex-direction: column !important; - width: 100% !important; - height: 100% !important; - position: relative !important; /* Override reset - needed for absolute children */ - overflow: visible !important; /* Allow dropdown to overflow container */ - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important; - text-align: left !important; - ${p?` - /* Theme Variables */ - ${p}`:""} - } - - /* Force left alignment for all elements in the editor */ - .overtype-container .overtype-wrapper * { - text-align: left !important; - } - - /* Auto-resize mode styles */ - .overtype-container.overtype-auto-resize { - height: auto !important; - } - - .overtype-container.overtype-auto-resize .overtype-wrapper { - flex: 0 0 auto !important; /* Don't grow/shrink, use explicit height */ - height: auto !important; - min-height: 60px !important; - overflow: visible !important; - } - - .overtype-wrapper { - position: relative !important; /* Override reset - needed for absolute children */ - width: 100% !important; - flex: 1 1 0 !important; /* Grow to fill remaining space, with flex-basis: 0 */ - min-height: 60px !important; /* Minimum usable height */ - overflow: hidden !important; - background: var(--bg-secondary, #ffffff) !important; - z-index: 1; /* Below toolbar and dropdown */ - } - - /* Critical alignment styles - must be identical for both layers */ - .overtype-wrapper .overtype-input, - .overtype-wrapper .overtype-preview { - /* Positioning - must be identical */ - position: absolute !important; /* Override reset - required for overlay */ - top: 0 !important; - left: 0 !important; - width: 100% !important; - height: 100% !important; - - /* Font properties - any difference breaks alignment */ - font-family: ${n} !important; - font-variant-ligatures: none !important; /* keep metrics stable for code */ - font-size: var(--instance-font-size, ${e}) !important; - line-height: var(--instance-line-height, ${t}) !important; - font-weight: normal !important; - font-style: normal !important; - font-variant: normal !important; - font-stretch: normal !important; - font-kerning: none !important; - font-feature-settings: normal !important; - - /* Box model - must match exactly */ - padding: var(--instance-padding, ${i}) !important; - margin: 0 !important; - border: none !important; - outline: none !important; - box-sizing: border-box !important; - - /* Text layout - critical for character positioning */ - white-space: pre-wrap !important; - word-wrap: break-word !important; - word-break: normal !important; - overflow-wrap: break-word !important; - tab-size: 2 !important; - -moz-tab-size: 2 !important; - text-align: left !important; - text-indent: 0 !important; - letter-spacing: normal !important; - word-spacing: normal !important; - - /* Text rendering */ - text-transform: none !important; - text-rendering: auto !important; - -webkit-font-smoothing: auto !important; - -webkit-text-size-adjust: 100% !important; - - /* Direction and writing */ - direction: ltr !important; - writing-mode: horizontal-tb !important; - unicode-bidi: normal !important; - text-orientation: mixed !important; - - /* Visual effects that could shift perception */ - text-shadow: none !important; - filter: none !important; - transform: none !important; - zoom: 1 !important; - - /* Vertical alignment */ - vertical-align: baseline !important; - - /* Size constraints */ - min-width: 0 !important; - min-height: 0 !important; - max-width: none !important; - max-height: none !important; - - /* Overflow */ - overflow-y: auto !important; - overflow-x: auto !important; - /* overscroll-behavior removed to allow scroll-through to parent */ - scrollbar-width: auto !important; - scrollbar-gutter: auto !important; - - /* Animation/transition - disabled to prevent movement */ - animation: none !important; - transition: none !important; - } - - /* Input layer styles */ - .overtype-wrapper .overtype-input { - /* Layer positioning */ - z-index: 1 !important; - - /* Text visibility */ - color: transparent !important; - caret-color: var(--cursor, #f95738) !important; - background-color: transparent !important; - - /* Textarea-specific */ - resize: none !important; - appearance: none !important; - -webkit-appearance: none !important; - -moz-appearance: none !important; - - /* Prevent mobile zoom on focus */ - touch-action: manipulation !important; - - /* Disable autofill and spellcheck */ - autocomplete: off !important; - autocorrect: off !important; - autocapitalize: off !important; - spellcheck: false !important; - } - - .overtype-wrapper .overtype-input::selection { - background-color: var(--selection, rgba(244, 211, 94, 0.4)); - } - - /* Preview layer styles */ - .overtype-wrapper .overtype-preview { - /* Layer positioning */ - z-index: 0 !important; - pointer-events: none !important; - color: var(--text, #0d3b66) !important; - background-color: transparent !important; - - /* Prevent text selection */ - user-select: none !important; - -webkit-user-select: none !important; - -moz-user-select: none !important; - -ms-user-select: none !important; - } - - /* Defensive styles for preview child divs */ - .overtype-wrapper .overtype-preview div { - /* Reset any inherited styles */ - margin: 0 !important; - padding: 0 !important; - border: none !important; - text-align: left !important; - text-indent: 0 !important; - display: block !important; - position: static !important; - transform: none !important; - min-height: 0 !important; - max-height: none !important; - line-height: inherit !important; - font-size: inherit !important; - font-family: inherit !important; - } - - /* Markdown element styling - NO SIZE CHANGES */ - .overtype-wrapper .overtype-preview .header { - font-weight: bold !important; - } - - /* Header colors */ - .overtype-wrapper .overtype-preview .h1 { - color: var(--h1, #f95738) !important; - } - .overtype-wrapper .overtype-preview .h2 { - color: var(--h2, #ee964b) !important; - } - .overtype-wrapper .overtype-preview .h3 { - color: var(--h3, #3d8a51) !important; - } - - /* Semantic headers - flatten in edit mode */ - .overtype-wrapper .overtype-preview h1, - .overtype-wrapper .overtype-preview h2, - .overtype-wrapper .overtype-preview h3 { - font-size: inherit !important; - font-weight: bold !important; - margin: 0 !important; - padding: 0 !important; - display: inline !important; - line-height: inherit !important; - } - - /* Header colors for semantic headers */ - .overtype-wrapper .overtype-preview h1 { - color: var(--h1, #f95738) !important; - } - .overtype-wrapper .overtype-preview h2 { - color: var(--h2, #ee964b) !important; - } - .overtype-wrapper .overtype-preview h3 { - color: var(--h3, #3d8a51) !important; - } - - /* Lists - remove styling in edit mode */ - .overtype-wrapper .overtype-preview ul, - .overtype-wrapper .overtype-preview ol { - list-style: none !important; - margin: 0 !important; - padding: 0 !important; - display: block !important; /* Lists need to be block for line breaks */ - } - - .overtype-wrapper .overtype-preview li { - display: block !important; /* Each item on its own line */ - margin: 0 !important; - padding: 0 !important; - /* Don't set list-style here - let ul/ol control it */ - } - - /* Bold text */ - .overtype-wrapper .overtype-preview strong { - color: var(--strong, #ee964b) !important; - font-weight: bold !important; - } - - /* Italic text */ - .overtype-wrapper .overtype-preview em { - color: var(--em, #f95738) !important; - text-decoration-color: var(--em, #f95738) !important; - text-decoration-thickness: 1px !important; - font-style: italic !important; - } - - /* Strikethrough text */ - .overtype-wrapper .overtype-preview del { - color: var(--del, #ee964b) !important; - text-decoration: line-through !important; - text-decoration-color: var(--del, #ee964b) !important; - text-decoration-thickness: 1px !important; - } - - /* Inline code */ - .overtype-wrapper .overtype-preview code { - background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important; - color: var(--code, #0d3b66) !important; - padding: 0 !important; - border-radius: 2px !important; - font-family: inherit !important; - font-size: inherit !important; - line-height: inherit !important; - font-weight: normal !important; - } - - /* Code blocks - consolidated pre blocks */ - .overtype-wrapper .overtype-preview pre { - padding: 0 !important; - margin: 0 !important; - border-radius: 4px !important; - overflow-x: auto !important; - } - - /* Code block styling in normal mode - yellow background */ - .overtype-wrapper .overtype-preview pre.code-block { - background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important; - white-space: break-spaces !important; /* Prevent horizontal scrollbar that breaks alignment */ - } - - /* Code inside pre blocks - remove background */ - .overtype-wrapper .overtype-preview pre code { - background: transparent !important; - color: var(--code, #0d3b66) !important; - font-family: ${n} !important; /* Match textarea font exactly for alignment */ - } - - /* Blockquotes */ - .overtype-wrapper .overtype-preview .blockquote { - color: var(--blockquote, #5a7a9b) !important; - padding: 0 !important; - margin: 0 !important; - border: none !important; - } - - /* Links */ - .overtype-wrapper .overtype-preview a { - color: var(--link, #0d3b66) !important; - text-decoration: underline !important; - font-weight: normal !important; - } - - .overtype-wrapper .overtype-preview a:hover { - text-decoration: underline !important; - color: var(--link, #0d3b66) !important; - } - - /* Lists - no list styling */ - .overtype-wrapper .overtype-preview ul, - .overtype-wrapper .overtype-preview ol { - list-style: none !important; - margin: 0 !important; - padding: 0 !important; - } - - - /* Horizontal rules */ - .overtype-wrapper .overtype-preview hr { - border: none !important; - color: var(--hr, #5a7a9b) !important; - margin: 0 !important; - padding: 0 !important; - } - - .overtype-wrapper .overtype-preview .hr-marker { - color: var(--hr, #5a7a9b) !important; - opacity: 0.6 !important; - } - - /* Code fence markers - with background when not in code block */ - .overtype-wrapper .overtype-preview .code-fence { - color: var(--code, #0d3b66) !important; - background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important; - } - - /* Code block lines - background for entire code block */ - .overtype-wrapper .overtype-preview .code-block-line { - background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important; - } - - /* Remove background from code fence when inside code block line */ - .overtype-wrapper .overtype-preview .code-block-line .code-fence { - background: transparent !important; - } - - /* Raw markdown line */ - .overtype-wrapper .overtype-preview .raw-line { - color: var(--raw-line, #5a7a9b) !important; - font-style: normal !important; - font-weight: normal !important; - } - - /* Syntax markers */ - .overtype-wrapper .overtype-preview .syntax-marker { - color: var(--syntax-marker, rgba(13, 59, 102, 0.52)) !important; - opacity: 0.7 !important; - } - - /* List markers */ - .overtype-wrapper .overtype-preview .list-marker { - color: var(--list-marker, #ee964b) !important; - } - - /* Stats bar */ - - /* Stats bar - positioned by flexbox */ - .overtype-stats { - height: 40px !important; - padding: 0 20px !important; - background: #f8f9fa !important; - border-top: 1px solid #e0e0e0 !important; - display: flex !important; - justify-content: space-between !important; - align-items: center !important; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important; - font-size: 0.85rem !important; - color: #666 !important; - flex-shrink: 0 !important; /* Don't shrink */ - z-index: 10001 !important; /* Above link tooltip */ - position: relative !important; /* Enable z-index */ - } - - /* Dark theme stats bar */ - .overtype-container[data-theme="cave"] .overtype-stats { - background: var(--bg-secondary, #1D2D3E) !important; - border-top: 1px solid rgba(197, 221, 232, 0.1) !important; - color: var(--text, #c5dde8) !important; - } - - .overtype-stats .overtype-stat { - display: flex !important; - align-items: center !important; - gap: 5px !important; - white-space: nowrap !important; - } - - .overtype-stats .live-dot { - width: 8px !important; - height: 8px !important; - background: #4caf50 !important; - border-radius: 50% !important; - animation: overtype-pulse 2s infinite !important; - } - - @keyframes overtype-pulse { - 0%, 100% { opacity: 1; transform: scale(1); } - 50% { opacity: 0.6; transform: scale(1.2); } - } - - - /* Toolbar Styles */ - .overtype-toolbar { - display: flex !important; - align-items: center !important; - gap: 4px !important; - padding: 8px !important; /* Override reset */ - background: var(--toolbar-bg, var(--bg-primary, #f8f9fa)) !important; /* Override reset */ - border-bottom: 1px solid var(--toolbar-border, transparent) !important; /* Override reset */ - overflow-x: auto !important; /* Allow horizontal scrolling */ - overflow-y: hidden !important; /* Hide vertical overflow */ - -webkit-overflow-scrolling: touch !important; - flex-shrink: 0 !important; - height: auto !important; - position: relative !important; /* Override reset */ - z-index: 100 !important; /* Ensure toolbar is above wrapper */ - scrollbar-width: thin; /* Thin scrollbar on Firefox */ - } - - /* Thin scrollbar styling */ - .overtype-toolbar::-webkit-scrollbar { - height: 4px; - } - - .overtype-toolbar::-webkit-scrollbar-track { - background: transparent; - } - - .overtype-toolbar::-webkit-scrollbar-thumb { - background: rgba(0, 0, 0, 0.2); - border-radius: 2px; - } - - .overtype-toolbar-button { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - height: 32px; - padding: 0; - border: none; - border-radius: 6px; - background: transparent; - color: var(--toolbar-icon, var(--text-secondary, #666)); - cursor: pointer; - transition: all 0.2s ease; - flex-shrink: 0; - } - - .overtype-toolbar-button svg { - width: 20px; - height: 20px; - fill: currentColor; - } - - .overtype-toolbar-button:hover { - background: var(--toolbar-hover, var(--bg-secondary, #e9ecef)); - color: var(--toolbar-icon, var(--text-primary, #333)); - } - - .overtype-toolbar-button:active { - transform: scale(0.95); - } - - .overtype-toolbar-button.active { - background: var(--toolbar-active, var(--primary, #007bff)); - color: var(--toolbar-icon, var(--text-primary, #333)); - } - - .overtype-toolbar-button:disabled { - opacity: 0.5; - cursor: not-allowed; - } - - .overtype-toolbar-separator { - width: 1px; - height: 24px; - background: var(--border, #e0e0e0); - margin: 0 4px; - flex-shrink: 0; - } - - /* Adjust wrapper when toolbar is present */ - /* Mobile toolbar adjustments */ - @media (max-width: 640px) { - .overtype-toolbar { - padding: 6px; - gap: 2px; - } - - .overtype-toolbar-button { - width: 36px; - height: 36px; - } - - .overtype-toolbar-separator { - margin: 0 2px; - } - } - - /* Plain mode - hide preview and show textarea text */ - .overtype-container[data-mode="plain"] .overtype-preview { - display: none !important; - } - - .overtype-container[data-mode="plain"] .overtype-input { - color: var(--text, #0d3b66) !important; - /* Use system font stack for better plain text readability */ - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, - "Helvetica Neue", Arial, sans-serif !important; - } - - /* Ensure textarea remains transparent in overlay mode */ - .overtype-container:not([data-mode="plain"]) .overtype-input { - color: transparent !important; - } - - /* Dropdown menu styles */ - .overtype-toolbar-button { - position: relative !important; /* Override reset - needed for dropdown */ - } - - .overtype-toolbar-button.dropdown-active { - background: var(--toolbar-active, var(--hover-bg, #f0f0f0)); - } - - .overtype-dropdown-menu { - position: fixed !important; /* Fixed positioning relative to viewport */ - background: var(--bg-secondary, white) !important; /* Override reset */ - border: 1px solid var(--border, #e0e0e0) !important; /* Override reset */ - border-radius: 6px; - box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; /* Override reset */ - z-index: 10000; /* Very high z-index to ensure visibility */ - min-width: 150px; - padding: 4px 0 !important; /* Override reset */ - /* Position will be set via JavaScript based on button position */ - } - - .overtype-dropdown-item { - display: flex; - align-items: center; - width: 100%; - padding: 8px 12px; - border: none; - background: none; - text-align: left; - cursor: pointer; - font-size: 14px; - color: var(--text, #333); - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - } - - .overtype-dropdown-item:hover { - background: var(--hover-bg, #f0f0f0); - } - - .overtype-dropdown-item.active { - font-weight: 600; - } - - .overtype-dropdown-check { - width: 16px; - margin-right: 8px; - color: var(--h1, #007bff); - } - - .overtype-dropdown-icon { - width: 20px; - margin-right: 8px; - text-align: center; - } - - /* Preview mode styles */ - .overtype-container[data-mode="preview"] .overtype-input { - display: none !important; - } - - .overtype-container[data-mode="preview"] .overtype-preview { - pointer-events: auto !important; - user-select: text !important; - cursor: text !important; - } - - /* Hide syntax markers in preview mode */ - .overtype-container[data-mode="preview"] .syntax-marker { - display: none !important; - } - - /* Hide URL part of links in preview mode - extra specificity */ - .overtype-container[data-mode="preview"] .syntax-marker.url-part, - .overtype-container[data-mode="preview"] .url-part { - display: none !important; - } - - /* Hide all syntax markers inside links too */ - .overtype-container[data-mode="preview"] a .syntax-marker { - display: none !important; - } - - /* Headers - restore proper sizing in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1, - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2, - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important; - font-weight: 600 !important; - margin: 0 !important; - display: block !important; - color: inherit !important; /* Use parent text color */ - line-height: 1 !important; /* Tight line height for headings */ - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1 { - font-size: 2em !important; - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2 { - font-size: 1.5em !important; - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3 { - font-size: 1.17em !important; - } - - /* Lists - restore list styling in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview ul { - display: block !important; - list-style: disc !important; - padding-left: 2em !important; - margin: 1em 0 !important; - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview ol { - display: block !important; - list-style: decimal !important; - padding-left: 2em !important; - margin: 1em 0 !important; - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li { - display: list-item !important; - margin: 0 !important; - padding: 0 !important; - } - - /* Task list checkboxes - only in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li.task-list { - list-style: none !important; - position: relative !important; - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li.task-list input[type="checkbox"] { - margin-right: 0.5em !important; - cursor: default !important; - vertical-align: middle !important; - } - - /* Task list in normal mode - keep syntax visible */ - .overtype-container:not([data-mode="preview"]) .overtype-wrapper .overtype-preview li.task-list { - list-style: none !important; - } - - .overtype-container:not([data-mode="preview"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker { - color: var(--syntax, #999999) !important; - font-weight: normal !important; - } - - /* Links - make clickable in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview a { - pointer-events: auto !important; - cursor: pointer !important; - color: var(--link, #0066cc) !important; - text-decoration: underline !important; - } - - /* Code blocks - proper pre/code styling in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block { - background: #2d2d2d !important; - color: #f8f8f2 !important; - padding: 1.2em !important; - border-radius: 3px !important; - overflow-x: auto !important; - margin: 0 !important; - display: block !important; - } - - /* Cave theme code block background in preview mode */ - .overtype-container[data-theme="cave"][data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block { - background: #11171F !important; - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block code { - background: transparent !important; - color: inherit !important; - padding: 0 !important; - font-family: ${n} !important; - font-size: 0.9em !important; - line-height: 1.4 !important; - } - - /* Hide old code block lines and fences in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .code-block-line { - display: none !important; - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .code-fence { - display: none !important; - } - - /* Blockquotes - enhanced styling in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .blockquote { - display: block !important; - border-left: 4px solid var(--blockquote, #ddd) !important; - padding-left: 1em !important; - margin: 1em 0 !important; - font-style: italic !important; - } - - /* Typography improvements in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview { - font-family: Georgia, 'Times New Roman', serif !important; - font-size: 16px !important; - line-height: 1.8 !important; - color: var(--text, #333) !important; /* Consistent text color */ - } - - /* Inline code in preview mode - keep monospace */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview code { - font-family: ${n} !important; - font-size: 0.9em !important; - background: rgba(135, 131, 120, 0.15) !important; - padding: 0.2em 0.4em !important; - border-radius: 3px !important; - } - - /* Strong and em elements in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview strong { - font-weight: 700 !important; - color: inherit !important; /* Use parent text color */ - } - - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview em { - font-style: italic !important; - color: inherit !important; /* Use parent text color */ - } - - /* HR in preview mode */ - .overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .hr-marker { - display: block !important; - border-top: 2px solid var(--hr, #ddd) !important; - text-indent: -9999px !important; - height: 2px !important; - } - - /* Link Tooltip - Base styles (all browsers) */ - .overtype-link-tooltip { - /* Visual styles that work for both positioning methods */ - background: #333 !important; - color: white !important; - padding: 6px 10px !important; - border-radius: 16px !important; - font-size: 12px !important; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important; - display: none !important; - z-index: 10000 !important; - cursor: pointer !important; - box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important; - max-width: 300px !important; - white-space: nowrap !important; - overflow: hidden !important; - text-overflow: ellipsis !important; - - /* Base positioning for Floating UI fallback */ - position: absolute; - } - - .overtype-link-tooltip.visible { - display: flex !important; - } - - /* CSS Anchor Positioning (modern browsers only) */ - @supports (position-anchor: --x) and (position-area: center) { - .overtype-link-tooltip { - /* Only anchor positioning specific properties */ - position-anchor: var(--target-anchor, --link-0); - position-area: block-end center; - margin-top: 8px !important; - position-try: most-width block-end inline-end, flip-inline, block-start center; - position-visibility: anchors-visible; - } - } - - ${a} - `}var Ke=Object.defineProperty,oe=Object.getOwnPropertySymbols,Ge=Object.prototype.hasOwnProperty,Ze=Object.prototype.propertyIsEnumerable,ie=(o,e,t)=>e in o?Ke(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,re=(o,e)=>{for(var t in e||(e={}))Ge.call(e,t)&&ie(o,t,e[t]);if(oe)for(var t of oe(e))Ze.call(e,t)&&ie(o,t,e[t]);return o},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Je(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return re(re({},Je()),o)}var q=!1;function Qe(){return q}function b(o,e,t){q&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function R(o,e){if(!q)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function ce(o){q&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function P(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Qe();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),p=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(p.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` + `:"",p=r&&r.colors?_(r.colors):"";return` .overtype-container *{margin:0 !important;padding:0 !important;border:0 !important;float:none !important;clear:none !important;text-decoration:none !important;text-transform:none !important;letter-spacing:normal !important;box-shadow:none !important;text-shadow:none !important;box-sizing:border-box !important;}.overtype-container{display:flex !important;flex-direction:column !important;width:100% !important;height:100% !important;position:relative !important;overflow:visible !important;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif !important;text-align:left !important;${p?` ${p}`:""}}.overtype-container .overtype-wrapper *{text-align:left !important;}.overtype-container.overtype-auto-resize{height:auto !important;}.overtype-container.overtype-auto-resize .overtype-wrapper{flex:0 0 auto !important;height:auto !important;min-height:60px !important;overflow:visible !important;}.overtype-wrapper{position:relative !important;width:100% !important;flex:1 1 0 !important;min-height:60px !important;overflow:hidden !important;background:var(--bg-secondary,#ffffff) !important;z-index:1;}.overtype-wrapper .overtype-input,.overtype-wrapper .overtype-preview{position:absolute !important;top:0 !important;left:0 !important;width:100% !important;height:100% !important;font-family:${n}!important;font-variant-ligatures:none !important;font-size:var(--instance-font-size,${e}) !important;line-height:var(--instance-line-height,${t}) !important;font-weight:normal !important;font-style:normal !important;font-variant:normal !important;font-stretch:normal !important;font-kerning:none !important;font-feature-settings:normal !important;padding:var(--instance-padding,${i}) !important;margin:0 !important;border:none !important;outline:none !important;box-sizing:border-box !important;white-space:pre-wrap !important;word-wrap:break-word !important;word-break:normal !important;overflow-wrap:break-word !important;tab-size:2 !important;-moz-tab-size:2 !important;text-align:left !important;text-indent:0 !important;letter-spacing:normal !important;word-spacing:normal !important;text-transform:none !important;text-rendering:auto !important;-webkit-font-smoothing:auto !important;-webkit-text-size-adjust:100% !important;direction:ltr !important;writing-mode:horizontal-tb !important;unicode-bidi:normal !important;text-orientation:mixed !important;text-shadow:none !important;filter:none !important;transform:none !important;zoom:1 !important;vertical-align:baseline !important;min-width:0 !important;min-height:0 !important;max-width:none !important;max-height:none !important;overflow-y:auto !important;overflow-x:auto !important;scrollbar-width:auto !important;scrollbar-gutter:auto !important;animation:none !important;transition:none !important;}.overtype-wrapper .overtype-input{z-index:1 !important;color:transparent !important;caret-color:var(--cursor,#f95738) !important;background-color:transparent !important;resize:none !important;appearance:none !important;-webkit-appearance:none !important;-moz-appearance:none !important;touch-action:manipulation !important;autocomplete:off !important;autocorrect:off !important;autocapitalize:off !important;spellcheck:false !important;}.overtype-wrapper .overtype-input::selection{background-color:var(--selection,rgba(244,211,94,0.4));}.overtype-wrapper .overtype-preview{z-index:0 !important;pointer-events:none !important;color:var(--text,#0d3b66) !important;background-color:transparent !important;user-select:none !important;-webkit-user-select:none !important;-moz-user-select:none !important;-ms-user-select:none !important;}.overtype-wrapper .overtype-preview div{margin:0 !important;padding:0 !important;border:none !important;text-align:left !important;text-indent:0 !important;display:block !important;position:static !important;transform:none !important;min-height:0 !important;max-height:none !important;line-height:inherit !important;font-size:inherit !important;font-family:inherit !important;}.overtype-wrapper .overtype-preview .header{font-weight:bold !important;}.overtype-wrapper .overtype-preview .h1{color:var(--h1,#f95738) !important;}.overtype-wrapper .overtype-preview .h2{color:var(--h2,#ee964b) !important;}.overtype-wrapper .overtype-preview .h3{color:var(--h3,#3d8a51) !important;}.overtype-wrapper .overtype-preview h1,.overtype-wrapper .overtype-preview h2,.overtype-wrapper .overtype-preview h3{font-size:inherit !important;font-weight:bold !important;margin:0 !important;padding:0 !important;display:inline !important;line-height:inherit !important;}.overtype-wrapper .overtype-preview h1{color:var(--h1,#f95738) !important;}.overtype-wrapper .overtype-preview h2{color:var(--h2,#ee964b) !important;}.overtype-wrapper .overtype-preview h3{color:var(--h3,#3d8a51) !important;}.overtype-wrapper .overtype-preview ul,.overtype-wrapper .overtype-preview ol{list-style:none !important;margin:0 !important;padding:0 !important;display:block !important;}.overtype-wrapper .overtype-preview li{display:block !important;margin:0 !important;padding:0 !important;}.overtype-wrapper .overtype-preview strong{color:var(--strong,#ee964b) !important;font-weight:bold !important;}.overtype-wrapper .overtype-preview em{color:var(--em,#f95738) !important;text-decoration-color:var(--em,#f95738) !important;text-decoration-thickness:1px !important;font-style:italic !important;}.overtype-wrapper .overtype-preview del{color:var(--del,#ee964b) !important;text-decoration:line-through !important;text-decoration-color:var(--del,#ee964b) !important;text-decoration-thickness:1px !important;}.overtype-wrapper .overtype-preview code{background:var(--code-bg,rgba(244,211,94,0.4)) !important;color:var(--code,#0d3b66) !important;padding:0 !important;border-radius:2px !important;font-family:inherit !important;font-size:inherit !important;line-height:inherit !important;font-weight:normal !important;}.overtype-wrapper .overtype-preview pre{padding:0 !important;margin:0 !important;border-radius:4px !important;overflow-x:auto !important;}.overtype-wrapper .overtype-preview pre.code-block{background:var(--code-bg,rgba(244,211,94,0.4)) !important;white-space:break-spaces !important;}.overtype-wrapper .overtype-preview pre code{background:transparent !important;color:var(--code,#0d3b66) !important;font-family:${n}!important;}.overtype-wrapper .overtype-preview .blockquote{color:var(--blockquote,#5a7a9b) !important;padding:0 !important;margin:0 !important;border:none !important;}.overtype-wrapper .overtype-preview a{color:var(--link,#0d3b66) !important;text-decoration:underline !important;font-weight:normal !important;}.overtype-wrapper .overtype-preview a:hover{text-decoration:underline !important;color:var(--link,#0d3b66) !important;}.overtype-wrapper .overtype-preview ul,.overtype-wrapper .overtype-preview ol{list-style:none !important;margin:0 !important;padding:0 !important;}.overtype-wrapper .overtype-preview hr{border:none !important;color:var(--hr,#5a7a9b) !important;margin:0 !important;padding:0 !important;}.overtype-wrapper .overtype-preview .hr-marker{color:var(--hr,#5a7a9b) !important;opacity:0.6 !important;}.overtype-wrapper .overtype-preview .code-fence{color:var(--code,#0d3b66) !important;background:var(--code-bg,rgba(244,211,94,0.4)) !important;}.overtype-wrapper .overtype-preview .code-block-line{background:var(--code-bg,rgba(244,211,94,0.4)) !important;}.overtype-wrapper .overtype-preview .code-block-line .code-fence{background:transparent !important;}.overtype-wrapper .overtype-preview .raw-line{color:var(--raw-line,#5a7a9b) !important;font-style:normal !important;font-weight:normal !important;}.overtype-wrapper .overtype-preview .syntax-marker{color:var(--syntax-marker,rgba(13,59,102,0.52)) !important;opacity:0.7 !important;}.overtype-wrapper .overtype-preview .list-marker{color:var(--list-marker,#ee964b) !important;}.overtype-stats{height:40px !important;padding:0 20px !important;background:#f8f9fa !important;border-top:1px solid #e0e0e0 !important;display:flex !important;justify-content:space-between !important;align-items:center !important;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif !important;font-size:0.85rem !important;color:#666 !important;flex-shrink:0 !important;z-index:10001 !important;position:relative !important;}.overtype-container[data-theme="cave"] .overtype-stats{background:var(--bg-secondary,#1D2D3E) !important;border-top:1px solid rgba(197,221,232,0.1) !important;color:var(--text,#c5dde8) !important;}.overtype-stats .overtype-stat{display:flex !important;align-items:center !important;gap:5px !important;white-space:nowrap !important;}.overtype-stats .live-dot{width:8px !important;height:8px !important;background:#4caf50 !important;border-radius:50% !important;animation:overtype-pulse 2s infinite !important;}@keyframes overtype-pulse{0%,100%{opacity:1;transform:scale(1);}50%{opacity:0.6;transform:scale(1.2);}}.overtype-toolbar{display:flex !important;align-items:center !important;gap:4px !important;padding:8px !important;background:var(--toolbar-bg,var(--bg-primary,#f8f9fa)) !important;border-bottom:1px solid var(--toolbar-border,transparent) !important;overflow-x:auto !important;overflow-y:hidden !important;-webkit-overflow-scrolling:touch !important;flex-shrink:0 !important;height:auto !important;position:relative !important;z-index:100 !important;scrollbar-width:thin;}.overtype-toolbar::-webkit-scrollbar{height:4px;}.overtype-toolbar::-webkit-scrollbar-track{background:transparent;}.overtype-toolbar::-webkit-scrollbar-thumb{background:rgba(0,0,0,0.2);border-radius:2px;}.overtype-toolbar-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:none;border-radius:6px;background:transparent;color:var(--toolbar-icon,var(--text-secondary,#666));cursor:pointer;transition:all 0.2s ease;flex-shrink:0;}.overtype-toolbar-button svg{width:20px;height:20px;fill:currentColor;}.overtype-toolbar-button:hover{background:var(--toolbar-hover,var(--bg-secondary,#e9ecef));color:var(--toolbar-icon,var(--text-primary,#333));}.overtype-toolbar-button:active{transform:scale(0.95);}.overtype-toolbar-button.active{background:var(--toolbar-active,var(--primary,#007bff));color:var(--toolbar-icon,var(--text-primary,#333));}.overtype-toolbar-button:disabled{opacity:0.5;cursor:not-allowed;}.overtype-toolbar-separator{width:1px;height:24px;background:var(--border,#e0e0e0);margin:0 4px;flex-shrink:0;}@media (max-width:640px){.overtype-toolbar{padding:6px;gap:2px;}.overtype-toolbar-button{width:36px;height:36px;}.overtype-toolbar-separator{margin:0 2px;}}.overtype-container[data-mode="plain"] .overtype-preview{display:none !important;}.overtype-container[data-mode="plain"] .overtype-input{color:var(--text,#0d3b66) !important;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif !important;}.overtype-container:not([data-mode="plain"]) .overtype-input{color:transparent !important;}.overtype-toolbar-button{position:relative !important;}.overtype-toolbar-button.dropdown-active{background:var(--toolbar-active,var(--hover-bg,#f0f0f0));}.overtype-dropdown-menu{position:fixed !important;background:var(--bg-secondary,white) !important;border:1px solid var(--border,#e0e0e0) !important;border-radius:6px;box-shadow:0 2px 8px rgba(0,0,0,0.1) !important;z-index:10000;min-width:150px;padding:4px 0 !important;}.overtype-dropdown-item{display:flex;align-items:center;width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;font-size:14px;color:var(--text,#333);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;}.overtype-dropdown-item:hover{background:var(--hover-bg,#f0f0f0);}.overtype-dropdown-item.active{font-weight:600;}.overtype-dropdown-check{width:16px;margin-right:8px;color:var(--h1,#007bff);}.overtype-dropdown-icon{width:20px;margin-right:8px;text-align:center;}.overtype-container[data-mode="preview"] .overtype-input{display:none !important;}.overtype-container[data-mode="preview"] .overtype-preview{pointer-events:auto !important;user-select:text !important;cursor:text !important;}.overtype-container[data-mode="preview"] .syntax-marker{display:none !important;}.overtype-container[data-mode="preview"] .syntax-marker.url-part,.overtype-container[data-mode="preview"] .url-part{display:none !important;}.overtype-container[data-mode="preview"] a .syntax-marker{display:none !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1,.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2,.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif !important;font-weight:600 !important;margin:0 !important;display:block !important;color:inherit !important;line-height:1 !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h1{font-size:2em !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h2{font-size:1.5em !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview h3{font-size:1.17em !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview ul{display:block !important;list-style:disc !important;padding-left:2em !important;margin:1em 0 !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview ol{display:block !important;list-style:decimal !important;padding-left:2em !important;margin:1em 0 !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li{display:list-item !important;margin:0 !important;padding:0 !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li.task-list{list-style:none !important;position:relative !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview li.task-list input[type="checkbox"]{margin-right:0.5em !important;cursor:default !important;vertical-align:middle !important;}.overtype-container:not([data-mode="preview"]) .overtype-wrapper .overtype-preview li.task-list{list-style:none !important;}.overtype-container:not([data-mode="preview"]) .overtype-wrapper .overtype-preview li.task-list .syntax-marker{color:var(--syntax,#999999) !important;font-weight:normal !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview a{pointer-events:auto !important;cursor:pointer !important;color:var(--link,#0066cc) !important;text-decoration:underline !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block{background:#2d2d2d !important;color:#f8f8f2 !important;padding:1.2em !important;border-radius:3px !important;overflow-x:auto !important;margin:0 !important;display:block !important;}.overtype-container[data-theme="cave"][data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block{background:#11171F !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block code{background:transparent !important;color:inherit !important;padding:0 !important;font-family:${n}!important;font-size:0.9em !important;line-height:1.4 !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .code-block-line{display:none !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .code-fence{display:none !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .blockquote{display:block !important;border-left:4px solid var(--blockquote,#ddd) !important;padding-left:1em !important;margin:1em 0 !important;font-style:italic !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview{font-family:Georgia,'Times New Roman',serif !important;font-size:16px !important;line-height:1.8 !important;color:var(--text,#333) !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview code{font-family:${n}!important;font-size:0.9em !important;background:rgba(135,131,120,0.15) !important;padding:0.2em 0.4em !important;border-radius:3px !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview strong{font-weight:700 !important;color:inherit !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview em{font-style:italic !important;color:inherit !important;}.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview .hr-marker{display:block !important;border-top:2px solid var(--hr,#ddd) !important;text-indent:-9999px !important;height:2px !important;}.overtype-link-tooltip{background:#333 !important;color:white !important;padding:6px 10px !important;border-radius:16px !important;font-size:12px !important;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif !important;display:none !important;z-index:10000 !important;cursor:pointer !important;box-shadow:0 2px 8px rgba(0,0,0,0.3) !important;max-width:300px !important;white-space:nowrap !important;overflow:hidden !important;text-overflow:ellipsis !important;position:absolute;}.overtype-link-tooltip.visible{display:flex !important;}@supports (position-anchor:--x) and (position-area:center){.overtype-link-tooltip{position-anchor:var(--target-anchor,--link-0);position-area:block-end center;margin-top:8px !important;position-try:most-width block-end inline-end,flip-inline,block-start center;position-visibility:anchors-visible;}}${a}`}var Ke=Object.defineProperty,oe=Object.getOwnPropertySymbols,Ge=Object.prototype.hasOwnProperty,Ze=Object.prototype.propertyIsEnumerable,ie=(o,e,t)=>e in o?Ke(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t,re=(o,e)=>{for(var t in e||(e={}))Ge.call(e,t)&&ie(o,t,e[t]);if(oe)for(var t of oe(e))Ze.call(e,t)&&ie(o,t,e[t]);return o},T={bold:{prefix:"**",suffix:"**",trimFirst:!0},italic:{prefix:"_",suffix:"_",trimFirst:!0},code:{prefix:"`",suffix:"`",blockPrefix:"```",blockSuffix:"```"},link:{prefix:"[",suffix:"](url)",replaceNext:"url",scanFor:"https?://"},bulletList:{prefix:"- ",multiline:!0,unorderedList:!0},numberedList:{prefix:"1. ",multiline:!0,orderedList:!0},quote:{prefix:"> ",multiline:!0,surroundWithNewlines:!0},taskList:{prefix:"- [ ] ",multiline:!0,surroundWithNewlines:!0},header1:{prefix:"# "},header2:{prefix:"## "},header3:{prefix:"### "},header4:{prefix:"#### "},header5:{prefix:"##### "},header6:{prefix:"###### "}};function Je(){return{prefix:"",suffix:"",blockPrefix:"",blockSuffix:"",multiline:!1,replaceNext:"",prefixSpace:!1,scanFor:"",surroundWithNewlines:!1,orderedList:!1,unorderedList:!1,trimFirst:!1}}function $(o){return re(re({},Je()),o)}var q=!1;function Qe(){return q}function b(o,e,t){q&&(console.group(`\u{1F50D} ${o}`),console.log(e),t&&console.log("Data:",t),console.groupEnd())}function R(o,e){if(!q)return;let t=o.value.slice(o.selectionStart,o.selectionEnd);console.group(`\u{1F4CD} Selection: ${e}`),console.log("Position:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Selected text:",JSON.stringify(t)),console.log("Length:",t.length);let n=o.value.slice(Math.max(0,o.selectionStart-10),o.selectionStart),i=o.value.slice(o.selectionEnd,Math.min(o.value.length,o.selectionEnd+10));console.log("Context:",JSON.stringify(n)+"[SELECTION]"+JSON.stringify(i)),console.groupEnd()}function ce(o){q&&(console.group("\u{1F4DD} Result"),console.log("Text to insert:",JSON.stringify(o.text)),console.log("New selection:",`${o.selectionStart}-${o.selectionEnd}`),console.groupEnd())}var H=null;function P(o,{text:e,selectionStart:t,selectionEnd:n}){let i=Qe();i&&(console.group("\u{1F527} insertText"),console.log("Current selection:",`${o.selectionStart}-${o.selectionEnd}`),console.log("Text to insert:",JSON.stringify(e)),console.log("New selection to set:",t,"-",n)),o.focus();let r=o.selectionStart,s=o.selectionEnd,a=o.value.slice(0,r),p=o.value.slice(s);i&&(console.log("Before text (last 20):",JSON.stringify(a.slice(-20))),console.log("After text (first 20):",JSON.stringify(p.slice(0,20))),console.log("Selected text being replaced:",JSON.stringify(o.value.slice(r,s))));let d=o.value,l=r!==s;if(H===null||H===!0){o.contentEditable="true";try{H=document.execCommand("insertText",!1,e),i&&console.log("execCommand returned:",H,"for text with",e.split(` `).length,"lines")}catch(c){H=!1,i&&console.log("execCommand threw error:",c)}o.contentEditable="false"}if(i&&(console.log("canInsertText before:",H),console.log("execCommand result:",H)),H){let c=a+e+p,u=o.value;i&&(console.log("Expected length:",c.length),console.log("Actual length:",u.length)),u!==c&&i&&(console.log("execCommand changed the value but not as expected"),console.log("Expected:",JSON.stringify(c.slice(0,100))),console.log("Actual:",JSON.stringify(u.slice(0,100))))}if(!H)if(i&&console.log("Using manual insertion"),o.value===d){i&&console.log("Value unchanged, doing manual replacement");try{document.execCommand("ms-beginUndoUnit")}catch(c){}o.value=a+e+p;try{document.execCommand("ms-endUndoUnit")}catch(c){}o.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))}else i&&console.log("Value was changed by execCommand, skipping manual insertion");i&&console.log("Setting selection range:",t,n),t!=null&&n!=null?o.setSelectionRange(t,n):o.setSelectionRange(r,o.selectionEnd),i&&(console.log("Final value length:",o.value.length),console.groupEnd())}function se(o){return o.trim().split(` `).length>1}function Xe(o,e){let t=e;for(;o[t]&&o[t-1]!=null&&!o[t-1].match(/\s/);)t--;return t}function Ye(o,e,t){let n=e,i=t?/\n/:/\s/;for(;o[n]&&!o[n].match(i);)n++;return n}function pe(o){let e=o.value.split(` `),t=0;for(let n=0;n=t&&o.selectionStart=t&&o.selectionEndnt(n,e),{adjustSelection:(n,i,r,s)=>{let a=o.value.slice(s,o.selectionEnd),p=/^\d+\.\s+/,d=/^- /,l=p.test(a),c=d.test(a),u=e.orderedList&&l||e.unorderedList&&c;if(i===r)if(u){let m=a.match(e.orderedList?p:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(i-g,s)}}else if(l||c){let m=a.match(l?p:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:i+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:i+m}}else if(u){let m=a.match(e.orderedList?p:d),g=m?m[0].length:0;return{start:Math.max(i-g,s),end:Math.max(r-g,s)}}else if(l||c){let m=a.match(l?p:d),g=m?m[0].length:0,v=(e.unorderedList?2:3)-g;return{start:i+v,end:r+v}}else{let m=e.unorderedList?2:3;return{start:i+m,end:r+m}}}});P(o,t)}function ot(o){if(!o)return[];let e=[],{selectionStart:t,selectionEnd:n,value:i}=o,r=i.split(` `),s=0,a="";for(let c of r){if(t>=s&&t<=s+c.length){a=c;break}s+=c.length+1}a.startsWith("- ")&&(a.startsWith("- [ ] ")||a.startsWith("- [x] ")?e.push("task-list"):e.push("bullet-list")),/^\d+\.\s/.test(a)&&e.push("numbered-list"),a.startsWith("> ")&&e.push("quote"),a.startsWith("# ")&&e.push("header"),a.startsWith("## ")&&e.push("header-2"),a.startsWith("### ")&&e.push("header-3");let p=Math.max(0,t-10),d=Math.min(i.length,n+10),l=i.slice(p,d);if(l.includes("**")){let c=i.slice(Math.max(0,t-100),t),u=i.slice(n,Math.min(i.length,n+100)),m=c.lastIndexOf("**"),g=u.indexOf("**");m!==-1&&g!==-1&&e.push("bold")}if(l.includes("_")){let c=i.slice(Math.max(0,t-100),t),u=i.slice(n,Math.min(i.length,n+100)),m=c.lastIndexOf("_"),g=u.indexOf("_");m!==-1&&g!==-1&&e.push("italic")}if(l.includes("`")){let c=i.slice(Math.max(0,t-100),t),u=i.slice(n,Math.min(i.length,n+100));c.includes("`")&&u.includes("`")&&e.push("code")}if(l.includes("[")&&l.includes("]")){let c=i.slice(Math.max(0,t-100),t),u=i.slice(n,Math.min(i.length,n+100)),m=c.lastIndexOf("["),g=u.indexOf("]");m!==-1&&g!==-1&&i.slice(n+g+1,n+g+10).startsWith("(")&&e.push("link")}return e}function ue(o){if(!o||o.disabled||o.readOnly)return;b("toggleBold","Starting"),R(o,"Before");let e=$(T.bold),t=U(o,e);ce(t),P(o,t),R(o,"After")}function me(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.italic),t=U(o,e);P(o,t)}function fe(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.code),t=U(o,e);P(o,t)}function ge(o,e={}){if(!o||o.disabled||o.readOnly)return;let t=o.value.slice(o.selectionStart,o.selectionEnd),n=$(T.link);if(t&&t.match(/^https?:\/\//)&&!e.url?(n.suffix=`](${t})`,n.replaceNext=""):e.url&&(n.suffix=`](${e.url})`,n.replaceNext=""),e.text&&!t){let s=o.selectionStart;o.value=o.value.slice(0,s)+e.text+o.value.slice(s),o.selectionStart=s,o.selectionEnd=s+e.text.length}let r=U(o,n);P(o,r)}function ve(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.bulletList);he(o,e)}function ye(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.numberedList);he(o,e)}function be(o){if(!o||o.disabled||o.readOnly)return;b("toggleQuote","Starting"),R(o,"Initial");let e=$(T.quote),t=V(o,n=>de(n,e),{prefix:e.prefix});ce(t),P(o,t),R(o,"Final")}function J(o){if(!o||o.disabled||o.readOnly)return;let e=$(T.taskList),t=V(o,n=>de(n,e),{prefix:e.prefix});P(o,t)}function Q(o,e=1,t=!1){if(!o||o.disabled||o.readOnly)return;(e<1||e>6)&&(e=1),b("insertHeader","============ START ============"),b("insertHeader",`Level: ${e}, Toggle: ${t}`),b("insertHeader",`Initial cursor: ${o.selectionStart}-${o.selectionEnd}`);let n=`header${e===1?"1":e}`,i=$(T[n]||T.header1);b("insertHeader",`Style prefix: "${i.prefix}"`);let r=o.value,s=o.selectionStart,a=o.selectionEnd,p=s;for(;p>0&&r[p-1]!==` `;)p--;let d=a;for(;d{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):u>0?(b("insertHeader",`ACTION: Replacing H${u} with H${e}`),x=i.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=i.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:i.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let B=Math.max(y-m,x);return b("insertHeader",` - Removing header, adjusting by -${m}`),{start:B,end:y===w?B:Math.max(w-m,x)}}else if(m>0){let B=i.prefix.length-m;return b("insertHeader",` - Replacing header, adjusting by ${B}`),{start:y+B,end:w+B}}else return b("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:y+i.prefix.length,end:w+i.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),P(o,f)}function we(o){Q(o,1,!0)}function xe(o){Q(o,2,!0)}function ke(o){Q(o,3,!0)}function Le(o){return ot(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Le)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=` - - - - - - - - `,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,n=this.findLinkAtPosition(t,e);n?(!this.currentLink||this.currentLink.url!==n.url||this.currentLink.index!==n.index)&&this.show(n):this.scheduleHide()}findLinkAtPosition(e,t){let n=/\[([^\]]+)\]\(([^)]+)\)/g,i,r=0;for(;(i=n.exec(e))!==null;){let s=i.index,a=i.index+i[0].length;if(t>=s&&t<=a)return{text:i[1],url:i[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let n=t.getBoundingClientRect();if(!(n.width===0||n.height===0))try{let{x:i,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${i}px`,top:`${r}px`,position:"absolute"})}catch(i){console.warn("Floating UI positioning failed:",i);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Ee=` - - -`,Te=` - - - -`,Ce=` - -`,Ae=` - -`,Me=` - -`,He=` - - - -`,$e=` - - - -`,Ie=` - - - - - - -`,Be=` - - - - - - - -`,Pe=` - - -`,_e=` - - - - - - -`,Ne=` - - -`;var k={bold:{name:"bold",actionId:"toggleBold",icon:Ee,title:"Bold (Ctrl+B)",action:({editor:o})=>{ue(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:$e,title:"Inline Code",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ce,title:"Heading 1",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Me,title:"Heading 3",action:({editor:o})=>{ke(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:Ie,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Be,title:"Numbered List",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:_e,title:"Task List",action:({editor:o})=>{J&&(J(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function ze(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function je(o){let e=o||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function rt(o,e){let t=je(o),n=je(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(h.prototype);return s._init(r,t),r.overTypeInstance=s,h.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++h.instanceCount,this.initialized=!1,h.injectStyles(),h.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||h.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=_(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||h.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=_(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=ze(N),this.options.toolbarButtons&&Object.assign(this.actionsById,ze(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;t{let y=v.value.slice(v.selectionStart,v.selectionEnd);b("insertHeader",`Line in operation: "${y}"`);let w=y.replace(/^#{1,6}\s*/,"");b("insertHeader",`Cleaned line: "${w}"`);let x;return g?(b("insertHeader","ACTION: Toggling OFF - removing header"),x=w):u>0?(b("insertHeader",`ACTION: Replacing H${u} with H${e}`),x=i.prefix+w):(b("insertHeader","ACTION: Adding new header"),x=i.prefix+w),b("insertHeader",`New line: "${x}"`),{text:x,selectionStart:v.selectionStart,selectionEnd:v.selectionEnd}},{prefix:i.prefix,adjustSelection:(v,y,w,x)=>{if(b("insertHeader","Adjusting selection:"),b("insertHeader",` - isRemoving param: ${v}`),b("insertHeader",` - shouldToggleOff: ${g}`),b("insertHeader",` - selStart: ${y}, selEnd: ${w}`),b("insertHeader",` - lineStartPos: ${x}`),g){let B=Math.max(y-m,x);return b("insertHeader",` - Removing header, adjusting by -${m}`),{start:B,end:y===w?B:Math.max(w-m,x)}}else if(m>0){let B=i.prefix.length-m;return b("insertHeader",` - Replacing header, adjusting by ${B}`),{start:y+B,end:w+B}}else return b("insertHeader",` - Adding header, adjusting by +${i.prefix.length}`),{start:y+i.prefix.length,end:w+i.prefix.length}}});b("insertHeader",`Final result: text="${f.text}", cursor=${f.selectionStart}-${f.selectionEnd}`),b("insertHeader","============ END ============"),P(o,f)}function we(o){Q(o,1,!0)}function xe(o){Q(o,2,!0)}function ke(o){Q(o,3,!0)}function Le(o){return ot(o)}var D=class{constructor(e,t={}){this.editor=e,this.container=null,this.buttons={},this.toolbarButtons=t.toolbarButtons||[]}create(){this.container=document.createElement("div"),this.container.className="overtype-toolbar",this.container.setAttribute("role","toolbar"),this.container.setAttribute("aria-label","Formatting toolbar"),this.toolbarButtons.forEach(e=>{if(e.name==="separator"){let t=this.createSeparator();this.container.appendChild(t)}else{let t=this.createButton(e);this.buttons[e.name]=t,this.container.appendChild(t)}}),this.editor.container.insertBefore(this.container,this.editor.wrapper)}createSeparator(){let e=document.createElement("div");return e.className="overtype-toolbar-separator",e.setAttribute("role","separator"),e}createButton(e){let t=document.createElement("button");return t.className="overtype-toolbar-button",t.type="button",t.setAttribute("data-button",e.name),t.title=e.title||"",t.setAttribute("aria-label",e.title||e.name),t.innerHTML=this.sanitizeSVG(e.icon||""),e.name==="viewMode"?(t.classList.add("has-dropdown"),t.dataset.dropdown="true",t.addEventListener("click",n=>{n.preventDefault(),this.toggleViewModeDropdown(t)}),t):(t._clickHandler=n=>{n.preventDefault();let i=e.actionId||e.name;this.editor.performAction(i,n)},t.addEventListener("click",t._clickHandler),t)}async handleAction(e){if(e&&typeof e=="object"&&typeof e.action=="function"){this.editor.textarea.focus();try{return await e.action({editor:this.editor,getValue:()=>this.editor.getValue(),setValue:t=>this.editor.setValue(t),event:null}),!0}catch(t){return console.error(`Action "${e.name}" error:`,t),this.editor.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{buttonName:e.name,error:t}})),!1}}return typeof e=="string"?this.editor.performAction(e,null):!1}sanitizeSVG(e){return typeof e!="string"?"":e.replace(/)<[^<]*)*<\/script>/gi,"").replace(/\son\w+\s*=\s*["'][^"']*["']/gi,"").replace(/\son\w+\s*=\s*[^\s>]*/gi,"")}toggleViewModeDropdown(e){let t=document.querySelector(".overtype-dropdown-menu");if(t){t.remove(),e.classList.remove("dropdown-active");return}e.classList.add("dropdown-active");let n=this.createViewModeDropdown(e),i=e.getBoundingClientRect();n.style.position="absolute",n.style.top=`${i.bottom+5}px`,n.style.left=`${i.left}px`,document.body.appendChild(n),this.handleDocumentClick=r=>{!n.contains(r.target)&&!e.contains(r.target)&&(n.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick))},setTimeout(()=>{document.addEventListener("click",this.handleDocumentClick)},0)}createViewModeDropdown(e){let t=document.createElement("div");t.className="overtype-dropdown-menu";let n=[{id:"normal",label:"Normal Edit",icon:"\u2713"},{id:"plain",label:"Plain Textarea",icon:"\u2713"},{id:"preview",label:"Preview Mode",icon:"\u2713"}],i=this.editor.container.dataset.mode||"normal";return n.forEach(r=>{let s=document.createElement("button");if(s.className="overtype-dropdown-item",s.type="button",s.textContent=r.label,r.id===i){s.classList.add("active"),s.setAttribute("aria-current","true");let a=document.createElement("span");a.className="overtype-dropdown-icon",a.textContent=r.icon,s.prepend(a)}s.addEventListener("click",a=>{switch(a.preventDefault(),r.id){case"plain":this.editor.showPlainTextarea();break;case"preview":this.editor.showPreviewMode();break;case"normal":default:this.editor.showNormalEditMode();break}t.remove(),e.classList.remove("dropdown-active"),document.removeEventListener("click",this.handleDocumentClick)}),t.appendChild(s)}),t}updateButtonStates(){var e;try{let t=((e=Le)==null?void 0:e(this.editor.textarea,this.editor.textarea.selectionStart))||[];Object.entries(this.buttons).forEach(([n,i])=>{if(n==="viewMode")return;let r=!1;switch(n){case"bold":r=t.includes("bold");break;case"italic":r=t.includes("italic");break;case"code":r=!1;break;case"bulletList":r=t.includes("bullet-list");break;case"orderedList":r=t.includes("numbered-list");break;case"taskList":r=t.includes("task-list");break;case"quote":r=t.includes("quote");break;case"h1":r=t.includes("header");break;case"h2":r=t.includes("header-2");break;case"h3":r=t.includes("header-3");break}i.classList.toggle("active",r),i.setAttribute("aria-pressed",r.toString())})}catch(t){}}destroy(){this.container&&(this.handleDocumentClick&&document.removeEventListener("click",this.handleDocumentClick),Object.values(this.buttons).forEach(e=>{e._clickHandler&&(e.removeEventListener("click",e._clickHandler),delete e._clickHandler)}),this.container.remove(),this.container=null,this.buttons={})}};var W=class{constructor(e){this.editor=e,this.tooltip=null,this.currentLink=null,this.hideTimeout=null,this.visibilityChangeHandler=null,this.useFloatingUI=!1,this.floatingUI=null,this.isTooltipHovered=!1,this.init()}async init(){if(!(CSS.supports("position-anchor: --x")&&CSS.supports("position-area: center")))try{let t=new Function("url","return import(url)"),{computePosition:n,offset:i,shift:r,flip:s}=await t("https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.7.4/+esm");this.floatingUI={computePosition:n,offset:i,shift:r,flip:s},this.useFloatingUI=!0}catch(t){console.warn("Failed to load Floating UI fallback:",t),this.floatingUI=null,this.useFloatingUI=!1}this.createTooltip(),this.editor.textarea.addEventListener("selectionchange",()=>this.checkCursorPosition()),this.editor.textarea.addEventListener("keyup",t=>{(t.key.includes("Arrow")||t.key==="Home"||t.key==="End")&&this.checkCursorPosition()}),this.editor.textarea.addEventListener("input",()=>this.hide()),this.editor.textarea.addEventListener("scroll",()=>{this.useFloatingUI&&this.currentLink?this.showWithFloatingUI(this.currentLink):this.hide()}),this.editor.textarea.addEventListener("blur",()=>{this.isTooltipHovered||this.hide()}),this.visibilityChangeHandler=()=>{document.hidden&&this.hide()},document.addEventListener("visibilitychange",this.visibilityChangeHandler),this.tooltip.addEventListener("mouseenter",()=>{this.isTooltipHovered=!0,this.cancelHide()}),this.tooltip.addEventListener("mouseleave",()=>{this.isTooltipHovered=!1,this.scheduleHide()})}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="overtype-link-tooltip",this.tooltip.innerHTML=``,this.tooltip.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),this.currentLink&&(window.open(this.currentLink.url,"_blank"),this.hide())}),this.editor.container.appendChild(this.tooltip)}checkCursorPosition(){let e=this.editor.textarea.selectionStart,t=this.editor.textarea.value,n=this.findLinkAtPosition(t,e);n?(!this.currentLink||this.currentLink.url!==n.url||this.currentLink.index!==n.index)&&this.show(n):this.scheduleHide()}findLinkAtPosition(e,t){let n=/\[([^\]]+)\]\(([^)]+)\)/g,i,r=0;for(;(i=n.exec(e))!==null;){let s=i.index,a=i.index+i[0].length;if(t>=s&&t<=a)return{text:i[1],url:i[2],index:r,start:s,end:a};r++}return null}show(e){this.currentLink=e,this.cancelHide();let t=this.tooltip.querySelector(".overtype-link-tooltip-url");t.textContent=e.url,this.useFloatingUI?this.showWithFloatingUI(e):this.showWithAnchorPositioning(e),this.tooltip.classList.add("visible")}showWithAnchorPositioning(e){this.tooltip.style.setProperty("--target-anchor",`--link-${e.index}`)}async showWithFloatingUI(e){let t=this.findAnchorElement(e.index);if(!t)return;let n=t.getBoundingClientRect();if(!(n.width===0||n.height===0))try{let{x:i,y:r}=await this.floatingUI.computePosition(t,this.tooltip,{placement:"bottom",middleware:[this.floatingUI.offset(8),this.floatingUI.shift({padding:8}),this.floatingUI.flip()]});Object.assign(this.tooltip.style,{left:`${i}px`,top:`${r}px`,position:"absolute"})}catch(i){console.warn("Floating UI positioning failed:",i);return}}findAnchorElement(e){return this.editor.preview.querySelector(`a[style*="--link-${e}"]`)}hide(){this.tooltip.classList.remove("visible"),this.currentLink=null,this.isTooltipHovered=!1}scheduleHide(){this.cancelHide(),this.hideTimeout=setTimeout(()=>this.hide(),300)}cancelHide(){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=null)}destroy(){this.cancelHide(),this.visibilityChangeHandler&&(document.removeEventListener("visibilitychange",this.visibilityChangeHandler),this.visibilityChangeHandler=null),this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null,this.currentLink=null,this.floatingUI=null,this.useFloatingUI=!1,this.isTooltipHovered=!1}};var Ee=``,Te=``,Ce=``,Ae=``,Me=``,He=``,$e=``,Ie=``,Be=``,Pe=``,_e=``,Ne=``;var k={bold:{name:"bold",actionId:"toggleBold",icon:Ee,title:"Bold (Ctrl+B)",action:({editor:o})=>{ue(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},italic:{name:"italic",actionId:"toggleItalic",icon:Te,title:"Italic (Ctrl+I)",action:({editor:o})=>{me(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},code:{name:"code",actionId:"toggleCode",icon:$e,title:"Inline Code",action:({editor:o})=>{fe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},separator:{name:"separator"},link:{name:"link",actionId:"insertLink",icon:He,title:"Insert Link",action:({editor:o})=>{ge(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h1:{name:"h1",actionId:"toggleH1",icon:Ce,title:"Heading 1",action:({editor:o})=>{we(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h2:{name:"h2",actionId:"toggleH2",icon:Ae,title:"Heading 2",action:({editor:o})=>{xe(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},h3:{name:"h3",actionId:"toggleH3",icon:Me,title:"Heading 3",action:({editor:o})=>{ke(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},bulletList:{name:"bulletList",actionId:"toggleBulletList",icon:Ie,title:"Bullet List",action:({editor:o})=>{ve(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},orderedList:{name:"orderedList",actionId:"toggleNumberedList",icon:Be,title:"Numbered List",action:({editor:o})=>{ye(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},taskList:{name:"taskList",actionId:"toggleTaskList",icon:_e,title:"Task List",action:({editor:o})=>{J&&(J(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0})))}},quote:{name:"quote",actionId:"toggleQuote",icon:Pe,title:"Quote",action:({editor:o})=>{be(o.textarea),o.textarea.dispatchEvent(new Event("input",{bubbles:!0}))}},viewMode:{name:"viewMode",icon:Ne,title:"View mode"}},N=[k.bold,k.italic,k.code,k.separator,k.link,k.separator,k.h1,k.h2,k.h3,k.separator,k.bulletList,k.orderedList,k.taskList,k.separator,k.quote,k.separator,k.viewMode];function ze(o){let e={};return(o||[]).forEach(t=>{if(!t||t.name==="separator")return;let n=t.actionId||t.name;t.action&&(e[n]=t.action)}),e}function je(o){let e=o||N;return Array.isArray(e)?e.map(t=>({name:(t==null?void 0:t.name)||null,actionId:(t==null?void 0:t.actionId)||(t==null?void 0:t.name)||null,icon:(t==null?void 0:t.icon)||null,title:(t==null?void 0:t.title)||null})):null}function rt(o,e){let t=je(o),n=je(e);if(t===null||n===null)return t!==n;if(t.length!==n.length)return!0;for(let i=0;i{if(r.overTypeInstance)return r.overTypeInstance.reinit(t),r.overTypeInstance;let s=Object.create(h.prototype);return s._init(r,t),r.overTypeInstance=s,h.instances.set(r,s),s})}_init(e,t={}){this.element=e,this.instanceTheme=t.theme||null,this.autoThemeMediaQuery=null,this.autoThemeListener=null,this.options=this._mergeOptions(t),this.instanceId=++h.instanceCount,this.initialized=!1,h.injectStyles(),h.initGlobalListeners();let n=e.querySelector(".overtype-container"),i=e.querySelector(".overtype-wrapper");n||i?this._recoverFromDOM(n,i):this._buildFromScratch(),this.instanceTheme&&this.setTheme(this.instanceTheme),this.shortcuts=new z(this),this._rebuildActionsMap(),this.linkTooltip=new W(this),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft})}),this.initialized=!0,this.options.onChange&&this.options.onChange(this.getValue(),this)}_mergeOptions(e){let t={fontSize:"14px",lineHeight:1.6,fontFamily:'"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',padding:"16px",mobile:{fontSize:"16px",padding:"12px",lineHeight:1.5},textareaProps:{},autofocus:!1,autoResize:!1,minHeight:"100px",maxHeight:null,placeholder:"Start typing...",value:"",onChange:null,onKeydown:null,showActiveLineRaw:!1,showStats:!1,toolbar:!1,toolbarButtons:null,statsFormatter:null,smartLists:!0,codeHighlighter:null},{theme:n,colors:i,...r}=e;return{...t,...r}}_recoverFromDOM(e,t){if(e&&e.classList.contains("overtype-container"))this.container=e,this.wrapper=e.querySelector(".overtype-wrapper");else if(t){this.wrapper=t,this.container=document.createElement("div"),this.container.className="overtype-container";let n=this.instanceTheme||h.currentTheme||A,i=typeof n=="string"?n:n.name;if(i&&this.container.setAttribute("data-theme",i),this.instanceTheme){let r=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(r&&r.colors){let s=_(r.colors);this.container.style.cssText+=s}}t.parentNode.insertBefore(this.container,t),this.container.appendChild(t)}if(!this.wrapper){e&&e.remove(),t&&t.remove(),this._buildFromScratch();return}if(this.textarea=this.wrapper.querySelector(".overtype-input"),this.preview=this.wrapper.querySelector(".overtype-preview"),!this.textarea||!this.preview){this.container.remove(),this._buildFromScratch();return}this.wrapper._instance=this,this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this._configureTextarea(),this._applyOptions()}_buildFromScratch(){let e=this._extractContent();this.element.innerHTML="",this._createDOM(),(e||this.options.value)&&this.setValue(e||this.options.value),this._applyOptions()}_extractContent(){let e=this.element.querySelector(".overtype-input");return e?e.value:this.element.textContent||""}_createDOM(){this.container=document.createElement("div"),this.container.className="overtype-container";let e=this.instanceTheme||h.currentTheme||A,t=typeof e=="string"?e:e.name;if(t&&this.container.setAttribute("data-theme",t),this.instanceTheme){let n=typeof this.instanceTheme=="string"?M(this.instanceTheme):this.instanceTheme;if(n&&n.colors){let i=_(n.colors);this.container.style.cssText+=i}}this.wrapper=document.createElement("div"),this.wrapper.className="overtype-wrapper",this.options.fontSize&&this.wrapper.style.setProperty("--instance-font-size",this.options.fontSize),this.options.lineHeight&&this.wrapper.style.setProperty("--instance-line-height",String(this.options.lineHeight)),this.options.padding&&this.wrapper.style.setProperty("--instance-padding",this.options.padding),this.wrapper._instance=this,this.textarea=document.createElement("textarea"),this.textarea.className="overtype-input",this.textarea.placeholder=this.options.placeholder,this._configureTextarea(),this.options.textareaProps&&Object.entries(this.options.textareaProps).forEach(([n,i])=>{n==="className"||n==="class"?this.textarea.className+=" "+i:n==="style"&&typeof i=="object"?Object.assign(this.textarea.style,i):this.textarea.setAttribute(n,i)}),this.preview=document.createElement("div"),this.preview.className="overtype-preview",this.preview.setAttribute("aria-hidden","true"),this.wrapper.appendChild(this.textarea),this.wrapper.appendChild(this.preview),this.container.appendChild(this.wrapper),this.options.showStats&&(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()),this.element.appendChild(this.container),this.options.autoResize?this._setupAutoResize():this.container.classList.remove("overtype-auto-resize")}_configureTextarea(){this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("data-gramm","false"),this.textarea.setAttribute("data-gramm_editor","false"),this.textarea.setAttribute("data-enable-grammarly","false")}_createToolbar(){let e=this.options.toolbarButtons||N;this.toolbar=new D(this,{toolbarButtons:e}),this.toolbar.create(),this._toolbarSelectionListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this._toolbarInputListener=()=>{this.toolbar&&this.toolbar.updateButtonStates()},this.textarea.addEventListener("selectionchange",this._toolbarSelectionListener),this.textarea.addEventListener("input",this._toolbarInputListener)}_cleanupToolbarListeners(){this._toolbarSelectionListener&&(this.textarea.removeEventListener("selectionchange",this._toolbarSelectionListener),this._toolbarSelectionListener=null),this._toolbarInputListener&&(this.textarea.removeEventListener("input",this._toolbarInputListener),this._toolbarInputListener=null)}_rebuildActionsMap(){this.actionsById=ze(N),this.options.toolbarButtons&&Object.assign(this.actionsById,ze(this.options.toolbarButtons))}_applyOptions(){this.options.autofocus&&this.textarea.focus(),this.options.autoResize?this.container.classList.contains("overtype-auto-resize")||this._setupAutoResize():this.container.classList.remove("overtype-auto-resize"),this.options.toolbar&&!this.toolbar?this._createToolbar():!this.options.toolbar&&this.toolbar&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null),this.updatePreview()}updatePreview(){let e=this.textarea.value,t=this.textarea.selectionStart,n=this._getCurrentLine(e,t),i=this.container.dataset.mode==="preview",r=S.parse(e,n,this.options.showActiveLineRaw,this.options.codeHighlighter,i);this.preview.innerHTML=r||'Start typing...',this._applyCodeBlockBackgrounds(),this.options.showStats&&this.statsBar&&this._updateStats(),this.options.onChange&&this.initialized&&this.options.onChange(e,this)}_applyCodeBlockBackgrounds(){let e=this.preview.querySelectorAll(".code-fence");for(let t=0;tc.replace(/^ /,"")).join(` `);document.execCommand?(this.textarea.setSelectionRange(n,i),document.execCommand("insertText",!1,l)):(this.textarea.value=s+l+p,this.textarea.selectionStart=n,this.textarea.selectionEnd=n+l.length)}else if(n!==i){let s=r.substring(0,n),a=r.substring(n,i),p=r.substring(i),l=a.split(` @@ -950,13 +49,7 @@ ${a}`:r;if(d){let L=o.value[o.selectionStart-1];o.selectionStart!==0&&L!=null&&! `),s=n.split(` `),a=0;for(let d=0;dthis.getValue(),setValue:s=>this.setValue(s),event:t}),!0}catch(s){return console.error(`OverType: Action "${e}" error:`,s),this.wrapper.dispatchEvent(new CustomEvent("button-error",{detail:{actionId:e,error:s}})),!1}}getRenderedHTML(e={}){let t=this.getValue(),n=S.parse(t,-1,!1,this.options.codeHighlighter);return e.cleanHTML&&(n=n.replace(/.*?<\/span>/g,""),n=n.replace(/\sclass="(bullet-list|ordered-list|code-fence|hr-marker|blockquote|url-part)"/g,""),n=n.replace(/\sclass=""/g,"")),n}getPreviewHTML(){return this.preview.innerHTML}getCleanHTML(){return this.getRenderedHTML({cleanHTML:!0})}focus(){this.textarea.focus()}blur(){this.textarea.blur()}isInitialized(){return this.initialized}reinit(e={}){var i;let t=(i=this.options)==null?void 0:i.toolbarButtons;this.options=this._mergeOptions({...this.options,...e});let n=this.toolbar&&this.options.toolbar&&rt(t,this.options.toolbarButtons);this._rebuildActionsMap(),n&&(this._cleanupToolbarListeners(),this.toolbar.destroy(),this.toolbar=null,this._createToolbar()),this._applyOptions(),this.updatePreview()}setTheme(e){if(this._cleanupAuto(),this.instanceTheme=e,e==="auto")this._setupAuto(),this._applyTheme(K("auto"));else{let t=typeof e=="string"?M(e):e,n=t.name||e;n&&this.container.setAttribute("data-theme",n),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}return this}_applyTheme(e){let t=M(e);this.container.setAttribute("data-theme","auto"),this.container.setAttribute("data-resolved-theme",e),t!=null&&t.colors&&(this.container.style.cssText+=_(t.colors)),this.updatePreview()}_setupAuto(){var e;window.matchMedia&&(h._autoInstances.add(this),h._mq||(h._mq=window.matchMedia("(prefers-color-scheme: dark)"),h._mqListener=t=>{let n=t.matches?"cave":"solar";h._autoInstances.forEach(i=>i._applyTheme(n))},(e=h._mq.addEventListener||h._mq.addListener)==null||e.call(h._mq,"change",h._mqListener)))}_cleanupAuto(){var e;h._autoInstances.delete(this),h._autoInstances.size===0&&h._mq&&((e=h._mq.removeEventListener||h._mq.removeListener)==null||e.call(h._mq,"change",h._mqListener),h._mq=null,h._mqListener=null)}setCodeHighlighter(e){this.options.codeHighlighter=e,this.updatePreview()}_updateStats(){if(!this.statsBar)return;let e=this.textarea.value,t=e.split(` `),n=e.length,i=e.split(/\s+/).filter(l=>l.length>0).length,r=this.textarea.selectionStart,a=e.substring(0,r).split(` -`),p=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:n,words:i,lines:t.length,line:p,column:d}):this.statsBar.innerHTML=` -
    - - ${n} chars, ${i} words, ${t.length} lines -
    -
    Line ${p}, Col ${d}
    - `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let p=e.scrollHeight;if(this.options.minHeight){let c=parseInt(this.options.minHeight);p=Math.max(p,c)}let d="hidden";if(this.options.maxHeight){let c=parseInt(this.options.maxHeight);p>c&&(p=c,d="auto")}let l=p+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==p&&(this.previousHeight=p)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,h.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new h(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let p=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[p]=h._parseDataValue(s.value)}return new h(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||h.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=h.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(h.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=h.currentTheme||A,i=ne({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),h.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let n=i=>{t?(i.setAttribute("data-theme","auto"),i.setAttribute("data-resolved-theme",e)):i.setAttribute("data-theme",e)};document.querySelectorAll(".overtype-container").forEach(n),document.querySelectorAll(".overtype-wrapper").forEach(i=>{var r;i.closest(".overtype-container")||n(i),(r=i._instance)==null||r.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(i=>{var r,s,a;(r=i.setAttribute)==null||r.call(i,"theme",t?"auto":e),t&&((s=i.setAttribute)==null||s.call(i,"data-resolved-theme",e)),(a=i.refreshTheme)==null||a.call(i)})}static setTheme(e,t=null){if(h._cleanupGlobalAuto(),e==="auto")h._setupGlobalAuto(),h._applyGlobalTheme(K("auto"),t,!0);else{let n=typeof e=="string"?M(e):e;t&&(n=G(n,t)),h.currentTheme=n,h.injectStyles(!0);let i=n.name||e;i&&h._updateThemeAttrs(i)}}static _applyGlobalTheme(e,t=null,n=!1){let i=M(e);t&&(i=G(i,t)),h.currentTheme=i,h.injectStyles(!0),h._updateThemeAttrs(e,n)}static _setupGlobalAuto(){var e;!window.matchMedia||h._globalAutoMq||(h._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),h._globalAutoListener=t=>{h._applyGlobalTheme(t.matches?"cave":"solar",null,!0)},(e=h._globalAutoMq.addEventListener||h._globalAutoMq.addListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener))}static _cleanupGlobalAuto(){var e;h._globalAutoMq&&h._globalAutoListener&&((e=h._globalAutoMq.removeEventListener||h._globalAutoMq.removeListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener),h._globalAutoMq=null,h._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){h.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),h.globalListenersInitialized=!0)}};E(h,"instances",new WeakMap),E(h,"stylesInjected",!1),E(h,"globalListenersInitialized",!1),E(h,"instanceCount",0),E(h,"_mq",null),E(h,"_mqListener",null),E(h,"_autoInstances",new Set),E(h,"_globalAutoMq",null),E(h,"_globalAutoListener",null);var I=h;I.MarkdownParser=S;I.ShortcutsManager=z;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var st=I;return De(at);})(); +`),p=a.length,d=a[a.length-1].length+1;this.options.statsFormatter?this.statsBar.innerHTML=this.options.statsFormatter({chars:n,words:i,lines:t.length,line:p,column:d}):this.statsBar.innerHTML=`
    ${n} chars, ${i} words, ${t.length} lines
    Line ${p}, Col ${d}
    `}_setupAutoResize(){this.container.classList.add("overtype-auto-resize"),this.previousHeight=null,this._updateAutoHeight(),this.textarea.addEventListener("input",()=>this._updateAutoHeight()),window.addEventListener("resize",()=>this._updateAutoHeight())}_updateAutoHeight(){if(!this.options.autoResize)return;let e=this.textarea,t=this.preview,n=this.wrapper,i=window.getComputedStyle(e),r=parseFloat(i.paddingTop),s=parseFloat(i.paddingBottom),a=e.scrollTop;e.style.setProperty("height","auto","important");let p=e.scrollHeight;if(this.options.minHeight){let c=parseInt(this.options.minHeight);p=Math.max(p,c)}let d="hidden";if(this.options.maxHeight){let c=parseInt(this.options.maxHeight);p>c&&(p=c,d="auto")}let l=p+"px";e.style.setProperty("height",l,"important"),e.style.setProperty("overflow-y",d,"important"),t.style.setProperty("height",l,"important"),t.style.setProperty("overflow-y",d,"important"),n.style.setProperty("height",l,"important"),e.scrollTop=a,t.scrollTop=a,this.previousHeight!==p&&(this.previousHeight=p)}showStats(e){this.options.showStats=e,e&&!this.statsBar?(this.statsBar=document.createElement("div"),this.statsBar.className="overtype-stats",this.container.appendChild(this.statsBar),this._updateStats()):e&&this.statsBar?this._updateStats():!e&&this.statsBar&&(this.statsBar.remove(),this.statsBar=null)}showNormalEditMode(){return this.container.dataset.mode="normal",this.updatePreview(),requestAnimationFrame(()=>{this.textarea.scrollTop=this.preview.scrollTop,this.textarea.scrollLeft=this.preview.scrollLeft}),this}showPlainTextarea(){if(this.container.dataset.mode="plain",this.toolbar){let e=this.container.querySelector('[data-action="toggle-plain"]');e&&(e.classList.remove("active"),e.title="Show markdown preview")}return this}showPreviewMode(){return this.container.dataset.mode="preview",this.updatePreview(),this}destroy(){if(this._cleanupAuto(),this.element.overTypeInstance=null,h.instances.delete(this.element),this.shortcuts&&this.shortcuts.destroy(),this.wrapper){let e=this.getValue();this.wrapper.remove(),this.element.textContent=e}this.initialized=!1}static init(e,t={}){return new h(e,t)}static initFromData(e,t={}){let n=document.querySelectorAll(e);return Array.from(n).map(i=>{let r={...t};for(let s of i.attributes)if(s.name.startsWith("data-ot-")){let p=s.name.slice(8).replace(/-([a-z])/g,(d,l)=>l.toUpperCase());r[p]=h._parseDataValue(s.value)}return new h(i,r)})}static _parseDataValue(e){return e==="true"?!0:e==="false"?!1:e==="null"?null:e!==""&&!isNaN(Number(e))?Number(e):e}static getInstance(e){return e.overTypeInstance||h.instances.get(e)||null}static destroyAll(){document.querySelectorAll("[data-overtype-instance]").forEach(t=>{let n=h.getInstance(t);n&&n.destroy()})}static injectStyles(e=!1){if(h.stylesInjected&&!e)return;let t=document.querySelector("style.overtype-styles");t&&t.remove();let n=h.currentTheme||A,i=ne({theme:n}),r=document.createElement("style");r.className="overtype-styles",r.textContent=i,document.head.appendChild(r),h.stylesInjected=!0}static _updateThemeAttrs(e,t=!1){let n=i=>{t?(i.setAttribute("data-theme","auto"),i.setAttribute("data-resolved-theme",e)):i.setAttribute("data-theme",e)};document.querySelectorAll(".overtype-container").forEach(n),document.querySelectorAll(".overtype-wrapper").forEach(i=>{var r;i.closest(".overtype-container")||n(i),(r=i._instance)==null||r.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(i=>{var r,s,a;(r=i.setAttribute)==null||r.call(i,"theme",t?"auto":e),t&&((s=i.setAttribute)==null||s.call(i,"data-resolved-theme",e)),(a=i.refreshTheme)==null||a.call(i)})}static setTheme(e,t=null){if(h._cleanupGlobalAuto(),e==="auto")h._setupGlobalAuto(),h._applyGlobalTheme(K("auto"),t,!0);else{let n=typeof e=="string"?M(e):e;t&&(n=G(n,t)),h.currentTheme=n,h.injectStyles(!0);let i=n.name||e;i&&h._updateThemeAttrs(i)}}static _applyGlobalTheme(e,t=null,n=!1){let i=M(e);t&&(i=G(i,t)),h.currentTheme=i,h.injectStyles(!0),h._updateThemeAttrs(e,n)}static _setupGlobalAuto(){var e;!window.matchMedia||h._globalAutoMq||(h._globalAutoMq=window.matchMedia("(prefers-color-scheme: dark)"),h._globalAutoListener=t=>{h._applyGlobalTheme(t.matches?"cave":"solar",null,!0)},(e=h._globalAutoMq.addEventListener||h._globalAutoMq.addListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener))}static _cleanupGlobalAuto(){var e;h._globalAutoMq&&h._globalAutoListener&&((e=h._globalAutoMq.removeEventListener||h._globalAutoMq.removeListener)==null||e.call(h._globalAutoMq,"change",h._globalAutoListener),h._globalAutoMq=null,h._globalAutoListener=null)}static setCodeHighlighter(e){S.setCodeHighlighter(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static setCustomSyntax(e){S.setCustomSyntax(e),document.querySelectorAll(".overtype-wrapper").forEach(t=>{let n=t._instance;n&&n.updatePreview&&n.updatePreview()}),document.querySelectorAll("overtype-editor").forEach(t=>{if(typeof t.getEditor=="function"){let n=t.getEditor();n&&n.updatePreview&&n.updatePreview()}})}static initGlobalListeners(){h.globalListenersInitialized||(document.addEventListener("input",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleInput(e)}}),document.addEventListener("keydown",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleKeydown(e)}}),document.addEventListener("scroll",e=>{if(e.target&&e.target.classList&&e.target.classList.contains("overtype-input")){let t=e.target.closest(".overtype-wrapper"),n=t==null?void 0:t._instance;n&&n.handleScroll(e)}},!0),document.addEventListener("selectionchange",e=>{let t=document.activeElement;if(t&&t.classList.contains("overtype-input")){let n=t.closest(".overtype-wrapper"),i=n==null?void 0:n._instance;i&&(i.options.showStats&&i.statsBar&&i._updateStats(),clearTimeout(i._selectionTimeout),i._selectionTimeout=setTimeout(()=>{i.updatePreview()},50))}}),h.globalListenersInitialized=!0)}};E(h,"instances",new WeakMap),E(h,"stylesInjected",!1),E(h,"globalListenersInitialized",!1),E(h,"instanceCount",0),E(h,"_mq",null),E(h,"_mqListener",null),E(h,"_autoInstances",new Set),E(h,"_globalAutoMq",null),E(h,"_globalAutoListener",null);var I=h;I.MarkdownParser=S;I.ShortcutsManager=z;I.themes={solar:A,cave:M("cave")};I.getTheme=M;I.currentTheme=A;var st=I;return De(at);})(); /** * OverType - A lightweight markdown editor library with perfect WYSIWYG alignment * @version 1.0.0